在Twig中的父作用域中设置变量

dis*_*ted 11 variables templates scope variable-assignment twig

在Smarty你可以做到

{$var = 'bla' scope=parent}
Run Code Online (Sandbox Code Playgroud)

在Twig有可能吗?

不建议使用块.我知道.我需要变量.

n3x*_*xus 11

base.twig

<title>{{ title|default('example.com') }} - My cool site</title>
Run Code Online (Sandbox Code Playgroud)

child.twig

{% set title = 'ChildTitle' %}
Run Code Online (Sandbox Code Playgroud)


ale*_*exw 10

如果您不想使用default()过滤器(即,当您想在父模板和子模板中多次使用变量时),您实际上可以在父模板中定义包含整个页面的块,然后嵌套您的其中的其他块:

{# base.twig #}

{# Default page properties.  You can override these in the `page` block of your child templates. #}
{% set page = page | default({}) | merge({
    "title"       : "My Default Title",
    "description" : "Default description"
}) %}

{% block page %}
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta name="description" content="{{ page.description }}"> 
            <title>{{ page.title }}</title>

            ...

        </head>
        <body>
            {% block content %}{% endblock %}
        </body>
    </html>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过设置值然后调用以下来覆盖子模板中块中的page变量:pageparent()

{# child.twig #}

{% extends "base.twig" %}

{% block page %}
    {# By putting this in a special block, we ensure that it will be set AFTER the default values are set in the parent template, 
    but BEFORE the page itself is rendered. #}

    {% set page = page | merge({
        "title"       : "Child Page",
        "description" : "Welcome to the child page!"
    }) %}    

    {{ parent() }}
{% endblock %}

{% block content %}
    ...
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

请注意,在父模板中,我们pagepage块外部定义变量,而在子模板中,我们在块定义它page.

因此,Twig将执行以下操作:

  1. 渲染时child.twig,它将从顶部开始base.twig,设置page变量的默认值.
  2. 当涉及到page 块时,它将看到child.twig覆盖的覆盖.因此,它将运行pagechild.twig.
  3. page块中child.twig,它将为page变量设置新值.然后它会调用parent(),告诉它返回base.twig并渲染父page块.
  4. 然后它将继续呈现页面,替换child.twig(在我的示例中,它将呈现content块)中定义的任何其他块.

在这里查看一个工作示例.请注意,当您开始添加多层继承时(例如,孙子模板),这会变得更加复杂.


Mos*_*oss 8

如果您只是想让子模板中的变量“可覆盖”,则可以像这样在父模板中设置变量:

{% set title = (title|default('My Page')) %}
Run Code Online (Sandbox Code Playgroud)

所以你可以设置这样的情况......

基枝

<html>
  <head>
    <title>{{title}}</title>
  </head>
  <body>
    {% block content %}
    {% end block %}
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

父.树枝

{% extends 'base.twig' %}

{% set title = (title|default('My Page')) %}
Run Code Online (Sandbox Code Playgroud)

小树枝

{% extends 'parent.twig' %} 

{% set title='My Subpage' %}   

{% block content %}
  This is the Sub-page.
{% end block %}
Run Code Online (Sandbox Code Playgroud)

最终结果将是:

<html>
  <head>
    <title>My Subpage</title>
  </head>
  <body>
    This is the Sub-page.
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

我认为这适用于大多数情况。父变量不是强制父变量被子变量覆盖,而是“让”变量被子变量覆盖。您还可以在父级中定义不同的行为,例如串联而不是覆盖。


Pet*_*vic 7

@ n3xus给出了一个很好的答案,它实际上也帮助了我(谢谢),但您可能还想从文档中查看此页面:Twig docs

一个特别好的功能是能够设置一大块text/html:

{% set title %}
    <i class="icon-user"></i>
    {{ user.username | capitalize }}
    <small>{{ user.email | lower }}</small>
{% endset %}
Run Code Online (Sandbox Code Playgroud)

可以轻松地从子模板生成非常具体的内容.