embed

这个 embed 标记结合了 includeextends . 它允许您包含另一个模板的内容,就像 include 做。但它也允许您覆盖包含的模板中定义的任何块,例如在扩展模板时。

将嵌入式模板视为“微布局骨架”。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{% embed "teasers_skeleton.twig" %}
    {# These blocks are defined in "teasers_skeleton.twig" #}
    {# and we override them right here:                    #}
    {% block left_teaser %}
        Some content for the left teaser box
    {% endblock %}
    {% block right_teaser %}
        Some content for the right teaser box
    {% endblock %}
{% endembed %}

这个 embed tag将模板继承的思想引入到内容片段的级别。虽然模板继承允许“文档骨架”(documentskeletons)由子模板填充,但是 embed 标签允许您为更小的内容单元创建“骨架”,并重复使用,并将其填充到任何您喜欢的地方。

由于用例可能不明显,让我们看一个简化的例子。设想一个由多个HTML页面共享的基本模板,它定义了一个名为“content”的块:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
┌─── page layout ─────────────────────┐
│                                     │
│           ┌── block "content" ──┐   │
│           │                     │   │
│           │                     │   │
│           │ (child template to  │   │
│           │  put content here)  │   │
│           │                     │   │
│           │                     │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

有些页面(“foo”和“bar”)共享相同的内容结构-两个垂直堆叠的框:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
┌─── page layout ─────────────────────┐
│                                     │
│           ┌── block "content" ──┐   │
│           │ ┌─ block "top" ───┐ │   │
│           │ │                 │ │   │
│           │ └─────────────────┘ │   │
│           │ ┌─ block "bottom" ┐ │   │
│           │ │                 │ │   │
│           │ └─────────────────┘ │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

而其他页面(“boom”和“baz”)共享不同的内容结构-两个框并排:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
┌─── page layout ─────────────────────┐
│                                     │
│           ┌── block "content" ──┐   │
│           │                     │   │
│           │ ┌ block ┐ ┌ block ┐ │   │
│           │ │"left" │ │"right"│ │   │
│           │ │       │ │       │ │   │
│           │ │       │ │       │ │   │
│           │ └───────┘ └───────┘ │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

没有 embed 标记,您有两种方法来设计模板:

  • 创建两个扩展主布局模板的“中间”基础模板:一个具有垂直堆叠的框,供“foo”和“bar”页面使用,另一个具有用于“boom”和“baz”页面的并排框。
  • 将顶部/底部和左/右框的标记直接嵌入到每个页面模板中。

这两种解决方案的扩展性不好,因为它们都有一个主要缺点:

  • 对于这个简化的例子,第一个解决方案确实可行。但是假设我们添加了一个侧边栏,它可能再次包含不同的、重复出现的内容结构。现在我们需要为所有内容结构和侧边栏结构的组合创建中间基模板。。。等等。
  • 第二种解决方案涉及到公共代码的复制及其所有负面后果:任何更改都涉及到查找和编辑结构的所有受影响副本,必须验证每个副本的正确性,副本可能因不小心的修改而失去同步等。

在这种情况下 embed 标签派上用场。通用的布局代码可以存在于一个基础模板中,两个不同的内容结构,我们称之为“微布局”进入单独的模板中,这些模板根据需要嵌入:

页面模板 foo.twig

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{% extends "layout_skeleton.twig" %}

{% block content %}
    {% embed "vertical_boxes_skeleton.twig" %}
        {% block top %}
            Some content for the top box
        {% endblock %}

        {% block bottom %}
            Some content for the bottom box
        {% endblock %}
    {% endembed %}
{% endblock %}

这是 vertical_boxes_skeleton.twig

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<div class="top_box">
    {% block top %}
        Top box default content
    {% endblock %}
</div>

<div class="bottom_box">
    {% block bottom %}
        Bottom box default content
    {% endblock %}
</div>

的目标 vertical_boxes_skeleton.twig 模板将分解出框的HTML标记。

这个 embed 标记的参数与 include 标签:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{% embed "base" with {'foo': 'bar'} %}
    ...
{% endembed %}

{% embed "base" with {'foo': 'bar'} only %}
    ...
{% endembed %}

{% embed "base" ignore missing %}
    ...
{% endembed %}

警告

由于嵌入式模板没有“名称”,因此如果更改上下文(例如,如果将CSS/JavaScript模板嵌入HTML模板中),基于模板名称的自动转义策略将无法按预期工作。在这种情况下,使用 autoescape 标签。

参见

include