56

是否有一般的“好”方法来实现此功能?我已经阅读了“使用”标签,这似乎是迄今为止最好的选择,但我仍然不喜欢它不会让我引入任何外部 html,只有块。

我将在下面的示例中使用“包含”标签来演示我试图描述的意图。

#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 %}
4

5 回答 5

68

我找到了解决方案。使用 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 %}
于 2013-08-10T10:24:20.973 回答
13

我在阅读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>

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

#templates/index.html.twig
{% extends 'base.html.twig' %}

并覆盖定义的块。但是,当我需要创建另一个使用这些骨架的页面时,如果我尝试在包含的另一个 _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 %}

<li>SubApp Menu Item</li>从未显示。尝试了很多事情extends,甚至没有运气的条件。

解决方案

embed标签解决子部分模板块被覆盖。

#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 %}

并简化 _partial 模板以仅具有所需的 html

#templates/subapp/_menu.html.twig 
    <li>SubApp Menu Item</li> 

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

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

于 2018-05-08T21:48:11.840 回答
3

可以办到。这是我通过将变量传递给视图来解决问题的方法。

#layout.twig
{% if sidebar is empty %}
    This is the default sidebar text.
{% else %}
    {% block sidebar %}{% endblock %}
{% endif %}
{% block content %}{% endblock %}

#index.twig
{% extends "layout.twig" %}
{% block sidebar %}
    This is the sidebar. It will override the default text.
{% endblock %}

{% block content %}
    This is the content.
{% endblock %}

#index.php (SlimPHP)
$app->render('index.twig', ['sidebar' => true]);

因为我使用的是 SlimPHP,所以我调用它的方式是将sidebar变量传递给视图。这可以通过使用传递给视图的不同变量来进一步扩展,因此您可以选择sidebar1sidebar2

于 2014-01-22T23:03:29.390 回答
0

我用一个非常简单的技巧让它工作:

基本上它的行为是这样的,因为没有 a{% extends "foo.html.twig" %}它就无法理解这些块并且只是将它们呈现在适当的位置。

所以让我们扩展......什么都没有:

{% extends "nothing.html.twig" %}

这实际上只是 1 个块:

# nothing.html.twig
{% block main %}
{% endblock %}

唯一的事情是您需要将所有内容包装在一个块中,这个假的“主”块。

于 2017-05-16T15:56:13.473 回答
0

@webberig 解决方案的改进,修复了所有扩展模板中未覆盖的块(@HerrNentu 评论):

#base.html.twig
{% if block("page_title") is defined %}
     {% include 'elements/header.html.twig' with {page_title: block('page_title')} %}
{% else %}
     {% include 'elements/header.html.twig' with {page_title: null} %}
{% endif %}
{% 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 %}
于 2020-03-05T08:56:43.737 回答