覆盖包含的Twig模板中的块

bru*_*ski 48 php twig

是否有一种通常"好"的方式来实现此功能?我已经阅读了关于'use'标签,这似乎是目前为止最好的选择,但我仍然不喜欢它不会让我带来任何外部HTML,只有块.

我将在下面的示例中使用'include'标记来演示我想要描述的意图.

#base.html.twig
{% include 'elements/header.html.twig' %}
{% block content %}{% endblock %}
{% include 'elements/footer.html.twig' %}

#header.html.twig
<h1>This is my header</h1>
{% block page_title %} Default Page Title {% endblock %}

#index.html.twig
{% extends 'layouts/base.html.twig' %}
{# I want to be able to do this somehow #}
{% block page_title %} This is my overridden page title {% endblock %}
{% block content %} here is the index page content {% endblock %}
Run Code Online (Sandbox Code Playgroud)

Web*_*rig 59

我找到了解决方案.使用block()函数获取子块的内容,并将其作为include语句中的变量传递给header.html.twig:

#base.html.twig
{% include 'elements/header.html.twig' with {page_title: block('page_title')} %}
{% block content %}{% endblock %}
{% include 'elements/footer.html.twig' %}

#header.html.twig
<h1>This is my header</h1>
{% if page_title is empty %}
Default Page Title
{% else %}
{{ page_title }}
{% endif %}

#index.html.twig
{% extends 'layouts/base.html.twig' %}
{% block page_title %} This is my overridden page title {% endblock %}
{% block content %} here is the index page content {% endblock %}
Run Code Online (Sandbox Code Playgroud)

  • 这仍然是最好的解决方案吗?在`include`中有一个`block`对我来说似乎微不足道. (5认同)
  • 如果`block`包含HTML,对我来说不起作用例如,如果你想要包含页眉,正文和页脚,并且在正文中有块体取代...你必须做`{{body | raw}} `而不是`{{body}}`所以HTML不会被转义. (3认同)

Mar*_*gis 7

我阅读了embed标签的文档,找到了一个不错的解决方案。我在Symfony 4中使用Twig 2.0。

我的结构

#templates/base.html.twig
{% block navbar %}
    <nav>
    {% block menu %}
        {% include '_menu' %}
    {% endblock menu %}
    </nav>
{% endblock navbar %}
{% block content %}
    {# several blocks defined #}
    {% block footer '' %}
{% endblock content %}

#templates/_menu.html.twig
<ul>
    {% block sub_app_menu_itens %}
        <li>Main App Menu Item</li>
    {% endblock sub_app_menu_itens %}
    <li>Menu item</li>
    <li>Another menu item</li>
    <li>Yet another menu item</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,当我创建index.html.twig时,唯一需要显示默认内容的代码是

#templates/index.html.twig
{% extends 'base.html.twig' %}
Run Code Online (Sandbox Code Playgroud)

并覆盖已定义的块。但是,当我需要创建使用这些框架的另一个页面时,如果我尝试覆盖包含的另一个_partial模板中的块sub_app_menu_itens,将无法正常工作。<li>Main App Menu Item</li>始终显示且永不覆盖(上面的代码)

#templates/subapp/index.html.twig
{% extends 'base.html.twig' %}
{% block title %}{{ 'agencia.homepage'|trans }}{% endblock %}
{% block menu %}
    {% include 'subapp/_menu.html.twig' %}
{% endblock menu %}
{% block user_content %}Content Here{% endblock %}

#templates/subapp/_menu.html.twig
{% extends '_menu.html.twig' %}
{% block sub_app_menu_itens %}
        <li>SubApp Menu Item</li> 
{% endblock sub_app_menu_itens %}
Run Code Online (Sandbox Code Playgroud)

<li>SubApp Menu Item</li>从未显示。尝试了很多类似的东西extends,甚至没有附带条件的条件。

解决方案

嵌入标签解决了孩子的部分模板块被覆盖。

#templates/subapp/index.html.twig
{% block menu %}
    {% embed '_menu.html.twig' %}
        {% block sub_app_menu_itens %}
            {% include 'subapp/_menu.html.twig' %}
        {% endblock sub_app_menu_itens %}
    {% endembed %}
{% endblock menu %}
Run Code Online (Sandbox Code Playgroud)

并将_partial模板简化为仅需要html

#templates/subapp/_menu.html.twig 
    <li>SubApp Menu Item</li> 
Run Code Online (Sandbox Code Playgroud)

现在<li>SubApp Menu Item</li>将显示在_menu模板的正确位置。

在层次上思考,一个include工作就像一个子层次(已解析),所有事物都只能在同一层次上覆盖,因此include不允许在另一个包含中覆盖。相反,embed模板被带到同一级别(未解析),因此您可以覆盖事物。