extends
¶
这个 extends
标记可用于从另一个模板扩展模板。
注解
和PHP一样,Twig不支持多重继承。所以每次渲染只能有一个extends标记。但是,Twig支持水平方向 reuse .
让我们定义一个基本模板, base.html
,它定义了一个简单的HTML框架文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!DOCTYPE html>
<html>
<head>
{% block head %}
<link rel="stylesheet" href="style.css"/>
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2011 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
|
在这个例子中, block 标记定义了子模板可以填充的四个块。
所有的 block
标记的作用是告诉模板引擎子模板可能会覆盖模板的这些部分。
子模板¶
子模板可能如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | {% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ parent() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome on my awesome homepage.
</p>
{% endblock %}
|
这个 extends
标签是这里的关键。它告诉模板引擎此模板“扩展”另一个模板。当模板系统评估此模板时,它首先找到父模板。extends标记应该是模板中的第一个标记。
注意,因为子模板没有定义 footer
块,使用父模板中的值。
不能定义多个 block
同一模板中具有相同名称的标记。存在这种限制是因为块标记在“两个”方向上工作。也就是说,块标记不仅提供了一个要填充的洞,它还定义了填充 起源 . 如果有两个相似的名字 block
标记在模板中,该模板的父级将不知道要使用哪个块的内容。
如果要多次打印块,则可以使用 block
功能:
1 2 3 | <title>{% block title %}{% endblock %}</title>
<h1>{{ block('title') }}</h1>
{% block body %}{% endblock %}
|
父块¶
可以使用 parent 功能。这将返回父块的结果:
1 2 3 4 5 | {% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
|
命名块结束标记¶
Twig允许您将块的名称放在结束标记之后,以提高可读性(名称位于 endblock
word必须与块名称匹配):
1 2 3 4 5 | {% block sidebar %}
{% block inner_sidebar %}
...
{% endblock inner_sidebar %}
{% endblock sidebar %}
|
块嵌套和范围¶
块可以嵌套用于更复杂的布局。默认情况下,块可以从外部范围访问变量:
1 2 3 | {% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
|
阻止快捷方式¶
对于内容很少的块,可以使用快捷语法。以下构造也会执行相同的操作:
1 2 3 | {% block title %}
{{ page_title|title }}
{% endblock %}
|
1 | {% block title page_title|title %}
|
动态继承¶
Twig通过使用变量作为基模板来支持动态继承:
1 | {% extends some_var %}
|
如果变量的计算结果为 \Twig\Template
或A \Twig\TemplateWrapper
实例,Twig将使用它作为父模板:
// {% extends layout %}
$layout = $twig->load('some_layout_template.twig');
$twig->display('template.twig', ['layout' => $layout]);
您还可以提供检查是否存在的模板列表。存在的第一个模板将用作父模板:
1 | {% extends ['layout.html', 'base_layout.html'] %}
|
有条件继承¶
由于父对象的模板名称可以是任何有效的Twig表达式,因此可以将继承机制设为条件:
1 | {% extends standalone ? "minimum.html" : "base.html" %}
|
在本例中,模板将扩展“最小值.html“布局模板如果 standalone
变量的计算结果为 true
,以及“基本.html“否则。
积木是如何工作的?¶
块提供了一种方法来更改模板的某个部分的呈现方式,但它不会以任何方式干扰其周围的逻辑。
让我们用下面的例子来说明块是如何工作的,更重要的是,它是如何不工作的:
1 2 3 4 5 6 7 | {# base.twig #}
{% for post in posts %}
{% block post %}
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
{% endblock %}
{% endfor %}
|
如果渲染此模板,无论是否使用 block
标签。这个 block
里面 for
循环只是使其可由子模板重写的一种方法:
1 2 3 4 5 6 7 8 9 | {# child.twig #}
{% extends "base.twig" %}
{% block post %}
<article>
<header>{{ post.title }}</header>
<section>{{ post.text }}</section>
</article>
{% endblock %}
|
现在,当呈现子模板时,循环将使用在子模板中定义的块,而不是在基模板中定义的块;然后执行的模板将等效于以下模板:
1 2 3 4 5 6 | {% for post in posts %}
<article>
<header>{{ post.title }}</header>
<section>{{ post.text }}</section>
</article>
{% endfor %}
|
让我们再举一个例子:包含在 if
声明:
1 2 3 4 5 6 7 | {% if posts is empty %}
{% block head %}
{{ parent() }}
<meta name="robots" content="noindex, follow">
{% endblock head %}
{% endif %}
|
与您可能认为的相反,此模板没有条件地定义块;它只是使子模板重写条件时将呈现的内容的输出 true
.
如果要有条件地显示输出,请改用以下命令:
1 2 3 4 5 6 7 | {% block head %}
{{ parent() }}
{% if posts is empty %}
<meta name="robots" content="noindex, follow">
{% endif %}
{% endblock head %}
|