php 覆盖包含的 Twig 模板中的块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17755818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overriding blocks within included Twig templates
提问by bruchowski
Is there a generally "good" way to achieve this functionality? I have read about the 'use' tag, which seems like the best option so far, but I still don't like that it wont let me bring in any outside html, only blocks.
是否有一种普遍的“好”方法来实现此功能?我已经阅读了关于“使用”标签的内容,这似乎是迄今为止最好的选择,但我仍然不喜欢它不会让我引入任何外部 html,只能引入块。
I will use the 'include' tag in the example below to demonstrate the intent I'm trying to describe.
我将在下面的示例中使用“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 %}
回答by Webberig
I found a solution. Use the block() function to get the child's block content and pass it to header.html.twig as a variable in the include statement:
我找到了解决方案。使用 block() 函数获取 child 的 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 %}
回答by Marcos Regis
I found a good and realsolution reading the documentationfor the embedtag. I'm using Twig 2.0 in Symfony 4.
我找到了一个很好的真正的解决方案,阅读了嵌入标签的文档。我在 Symfony 4 中使用 Twig 2.0。
My structure
我的结构
#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>
With code above, when I create my index.html.twigthe only code needed to show de default things is
使用上面的代码,当我创建index.html.twig时,显示默认内容所需的唯一代码是
#templates/index.html.twig
{% extends 'base.html.twig' %}
and override blocks defined.
But, when I need to create another page, that use these skeleton, if I try to override block sub_app_menu_itensin another _partial template included, doesn't work. <li>Main App Menu Item</li>
is always showed and never overwritten (code above)
并覆盖定义的块。但是,当我需要创建另一个使用这些框架的页面时,如果我尝试覆盖包含的另一个 _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>
is never showed. Tried a lot of things like extends
and even conditionals with no luck.
<li>SubApp Menu Item</li>
从未显示。extends
在没有运气的情况下尝试了很多类似甚至条件的事情。
THE Solution
解决方案
The embedtag solve the child partial templates blocks to be overwritten.
该嵌入标签解决了孩子的部分模板块被覆盖。
#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 %}
And simplifing _partial template to have only the html needed
并简化 _partial 模板以只需要 html
#templates/subapp/_menu.html.twig
<li>SubApp Menu Item</li>
Now <li>SubApp Menu Item</li>
will be displayed on the right place of _menu template.
现在<li>SubApp Menu Item</li>
将显示在 _menu 模板的正确位置。
Thinking in levels, a include
works like a sublevel (parsed) and all things are only override on the same level, so include
doesn't allow to override in another include. Instead, embed
templates are bring to the same level (not parsed) and so you can override things.
在层次上思考,一个include
像子层次(解析)一样工作,所有的东西都只在同一层次上覆盖,所以include
不允许在另一个包含中覆盖。相反,embed
模板被带到同一级别(未解析),因此您可以覆盖内容。
回答by kacperek
It can be done. Here's my solution to the problem by passing a variable to the view.
可以办到。这是我通过将变量传递给视图来解决问题的方法。
#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]);
Since I'm using SlimPHP the way I call it is by passing sidebar
variable to the the view. This can be extended further by using different variables passed to the view, so you can selected sidebar1
, sidebar2
etc.
因为我使用 SlimPHP,所以我调用它的方式是将sidebar
变量传递给视图。这可以进一步通过使用传递给视图不同的变量,所以可以选择被扩展sidebar1
,sidebar2
等等。
回答by lipsumar
I got it to work with a very simple hack:
我用一个非常简单的 hack 让它工作:
Basically it behaves this way because without a {% extends "foo.html.twig" %}
it doesn't understand the blocks and simply renders them in place.
基本上它的行为方式是这样的,因为没有 a{% extends "foo.html.twig" %}
它就无法理解这些块并简单地将它们渲染到位。
So let's extend... nothing:
所以让我们扩展......什么都没有:
{% extends "nothing.html.twig" %}
This nothing is really just 1 block:
这实际上只是 1 个块:
# nothing.html.twig
{% block main %}
{% endblock %}
The only thing is that you need to wrap everything in a block, this fake "main" block.
唯一的事情是你需要把所有东西都包装在一个块中,这个假的“主”块。
回答by WiRa
Improvement on @webberig's solution, that fixes blocks that are not overridden in all extending templates (comment by @HerrNentu'):
对@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 %}