包含、扩展、使用、宏、嵌入 Twig 之间的区别

Difference between Include, Extends, Use, Macro, Embed in Twig

Twig 中的 useinclude 有什么区别?

Documentation:

include

The include statement includes a template and returns the rendered content of that template into the current one:

{% include 'header.html' %}
Body here...
{% include 'footer.html' %}

use

The use statement tells Twig to import the blocks defined in blocks.html into the current template (it's like macros, but for blocks):

blocks.html

{% block sidebar %}{% endblock %}

main.html

{% extends "base.html" %}
{% use "blocks.html" %}
{% block title %}{% endblock %}
{% block content %}{% endblock %}

可能的答案:

我认为this应该解释一下区别:

include is to get all the code from an external file and import it into your actual file at the right location of the call.

use is completely different as it parses the linked file to find a particular section of code and then overwrites the blocks with the same name, in your current file, with the one found in this external file.

include is like "go find this file and render it with my page here".

use is "parse this other file to find block definitions to use instead of my owns defined here".

If use command finds nothing matching the task, nothing is displayed at all from this file.


问题

解释正确吗?对于这种差异还有其他解释吗?

几个月后,我发布了一个答案,供进一步参考这个问题。我还为 extends & import & macro & embed 添加了一些描述以获得更多许可:

Twig 中有多种类型的继承和代码重用:


包括

主要目标:代码重用

用例:base.html.twig.

中使用 header.html.twig & footer.html.twig

header.html.twig

<nav>
   <div>Homepage</div>
   <div>About</div>
</nav>

footer.html.twig

<footer>
   <div>Copyright</div>
</footer>

base.html.twig

{% include 'header.html.twig' %}
<main>{% block main %}{% endblock %}</main>
{% include 'footer.html.twig' %}

延长

主要目标:垂直再利用

用例:homepage.html.twig & about.html.twig.

中扩展 base.html.twig

base.html.twig

{% include 'header.html.twig' %}
<main>{% block main %}{% endblock %}</main>
{% include 'footer.html.twig' %}

homepage.html.twig

{% extends 'base.html.twig' %}

{% block main %}
<p>Homepage</p>
{% endblock %}

about.html.twig

{% extends 'base.html.twig' %}

{% block main %}
<p>About page</p>
{% endblock %}

使用

主要目标:水平再利用

用例: sidebar.html.twig in single.product.html.twig & single.service.html.twig.

sidebar.html.twig

{% block sidebar %}<aside>This is sidebar</aside>{% endblock %}

single.product.html.twig

{% extends 'product.layout.html.twig' %}

{% use 'sidebar.html.twig' %}

{% block main %}<main>Product page</main>{% endblock %}

single.service.html.twig

{% extends 'service.layout.html.twig' %}

{% use 'sidebar.html.twig' %}

{% block main %}<main>Service page</main>{% endblock %}

备注:

  1. 它类似于宏,但用于块。
  2. 如果 use 标签不扩展另一个模板、不定义宏并且主体为空,则 use 标签只导入一个模板。

主要目标: 带变量的可重用标记

用例: 获取一些变量并输出一些标记的函数。

form.html.twig

{% macro input(name, value, type) %}
    <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" }}" />
{% endmacro %}

profile.service.html.twig

{% import "form.html.twig" as form %}

<form action="/login" method="post">
    <div>{{ form.input('username') }}</div>
    <div>{{ form.input('password') }}</div>
    <div>{{ form.input('submit', 'Submit', 'submit') }}</div>
</form>

嵌入

主要目标: 阻止覆盖

用例:pagination.html.twig 嵌入 product.table.html.twig & service.table.html.twig.

pagination.html.twig

<div id="pagination">
    <div>{% block first %}{% endblock %}</div>
    {% for i in (min + 1)..(max - 1) %}
        <div>{{ i }}</div>
    {% endfor %}
    <div>{% block last %}{% endblock %}</div>
</div>

product.table.html.twig

{% set min, max = 1, products.itemPerPage %}

{% embed 'pagination.html.twig' %}
    {% block first %}First Product Page{% endblock %}
    {% block last %}Last Product Page{% endblock %}
{% endembed %}

service.table.html.twig

{% set min, max = 1, services.itemPerPage %}

{% embed 'pagination.html.twig' %}
    {% block first %}First Service Page{% endblock %}
    {% block last %}Last Service Page{% endblock %}
{% endembed %}

请注意,嵌入文件 (pagination.html.twig) 可以访问当前上下文(minmax 变量)。

您也可以将额外的变量传递给嵌入文件:

pagination.html.twig

<p>{{ count }} items</p>
<div>
    <div>{% block first %}{% endblock %}</div>
    {% for i in (min + 1)..(max - 1) %}
        <div>{{ i }}</div>
    {% endfor %}
    <div>{% block last %}{% endblock %}</div>
</div>

product.table.html.twig

{% set min, max = 1, products|length %}

{% embed 'pagination.html.twig' with {'count': products|length } %}
    {% block first %}First Product Page{% endblock %}
    {% block last %}Last Product Page{% endblock %}
{% endembed %}

注:

它同时具有 UseInclude 的功能。

Twig 的性能非常出色,因此您可能永远不会在意,但请注意使用嵌入、包含或宏之间存在显着差异

我设置了一个小测试项目来演示它:https://github.com/janklan/twig-benchmark

如果您有兴趣了解更多信息,自述文件包含您需要的所有信息,但一般结果是,对于在 100k 次迭代循环中执行的相同任务,我计算机上各个方法之间的时间是如下(越低越好)

  • 嵌入:4253 毫秒
  • 包括:3428ms
  • 宏:2695 毫秒

顺便说一下,我通过 Github up 共享的项目为每种方法 (embed/include/macro) 生成了单独的缓存目录。如果您想了解 Twig 中的不同方法如何映射到已编译的 PHP,我建议您查看一下。如果您希望在不 运行 项目的情况下查看缓存,请查看 a branch called with-cache