Twig

灵活、快速和安全的
PHP 模板引擎

a Symfony Product
文档 标签 extends
您正在阅读 Twig 3.x 的文档。切换到 Twig 1.x, 2.x 的文档。

问题与反馈

许可证

Twig 文档 基于新 BSD 许可证 授权。

extends

extends 标签可以用于从另一个模板扩展一个模板。

注意

与 PHP 类似,Twig 不支持多重继承。因此,每次渲染只能调用一个 extends 标签。但是,Twig 支持水平重用

让我们定义一个基础模板,base.html.twig,它定义了一个简单的 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 %}
                &copy; Copyright 2011 by <a href="https://example.com/">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.twig" %}

{% 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 单词后的名称必须与块名称匹配)

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\Twig\TemplateWrapper 实例,Twig 将使用它作为父模板

1
2
3
4
5
// {% extends layout %}

$layout = $twig->load('some_layout_template.html.twig');

$twig->display('template.html.twig', ['layout' => $layout]);

您还可以提供要检查是否存在的模板列表。第一个存在的模板将用作父模板

1
{% extends ['layout.html.twig', 'base_layout.html.twig'] %}

条件继承

由于父模板的模板名称可以是任何有效的 Twig 表达式,因此可以使继承机制具有条件性

1
{% extends standalone ? "minimum.html.twig" : "base.html.twig" %}

在此示例中,如果 standalone 变量评估为 true,则模板将扩展 “minimum.html.twig” 布局模板,否则扩展 “base.html.twig”。

块是如何工作的?

块提供了一种更改模板特定部分呈现方式的方法,但它不会以任何方式干扰其周围的逻辑。

让我们看下面的示例,以说明块的工作原理,更重要的是,它如何不工作

1
2
3
4
5
6
7
{# base.html.twig #}
{% for post in posts %}
    {% block post %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.body }}</p>
    {% endblock %}
{% endfor %}

如果渲染此模板,则无论有无 block 标签,结果都完全相同。for 循环内的 block 只是使其可被子模板覆盖的一种方式

1
2
3
4
5
6
7
8
9
{# child.html.twig #}
{% extends "base.html.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 %}

另请参阅

block, block, parent, use