【问题标题】:Set variable in parent scope in Twig在 Twig 的父范围内设置变量
【发布时间】:2013-11-08 06:06:19
【问题描述】:

在 Smarty 中你可以做到

{$var = 'bla' scope=parent}

在 Twig 中可以吗?

不建议使用积木。我知道。我需要变量。

【问题讨论】:

  • 您找到解决方案了吗?
  • @Cyrus,好久不见。我目前不喜欢 twig 或 php。我想我只是选择了最详尽的答案。

标签: templates variables scope twig variable-assignment


【解决方案1】:

如果您不想使用 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 %}

然后,您可以覆盖子模板中page 块中的page 变量,方法是设置值然后调用parent()

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

请注意,在父模板中,我们将page 变量定义在page 块之外,而在子模板中,我们将其page 块中定义。

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

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

查看工作示例here。请注意,当您开始添加多层继承(例如,孙模板)时,这可能会变得更加复杂。

【讨论】:

  • 谢谢。 {% set page = page | default({}) | merge({ 似乎正是我需要学习的。
【解决方案2】:

如果您只是想让子模板中的变量“可覆盖”,您可以在父模板中设置变量,如下所示:

{% set title = (title|default('My Page')) %}

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

base.twig

<html>
  <head>
    <title>{{title}}</title>
  </head>
  <body>
    {% block content %}
    {% end block %}
  </body>
</html>

父.twig

{% extends 'base.twig' %}

{% set title = (title|default('My Page')) %}

child.twig

{% extends 'parent.twig' %} 

{% set title='My Subpage' %}   

{% block content %}
  This is the Sub-page.
{% end block %}

最终结果将是:

<html>
  <head>
    <title>My Subpage</title>
  </head>
  <body>
    This is the Sub-page.
  </body>
</html>

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

【讨论】:

    【解决方案3】:

    base.twig

    <title>{{ title|default('example.com') }} - My cool site</title>
    

    child.twig

    {% set title = 'ChildTitle' %}
    

    【讨论】:

    • 我相信这只有在set title 设置在&lt;title&gt; 标签之前设置为你有上面。是否有解决方案将title 变量设置在 模板中的&lt;title&gt; 标记之后?
    【解决方案4】:

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

    一个特别好的功能是能够设置一段文本/html:

    {% set title %}
        <i class="icon-user"></i>
        {{ user.username | capitalize }}
        <small>{{ user.email | lower }}</small>
    {% endset %}
    

    使从子模板生成非常具体的内容变得容易。

    【讨论】:

      【解决方案5】:

      您可以在子页面中使用以下内容:

      {% set title = 'your desired title' %}
      

      【讨论】:

        【解决方案6】:

        我刚刚发现了一个很好的方法来做这样的事情:

        父.twig

        {% set subvar = block('subvar') %}
        
        {# somewhere later #}
        
        {{ subvar }}
        

        child.twig

        {% block subvar %}
            anything you want
        {% endblock %}
        

        如果您的子模板未定义块subvar,则parent.twig 中的变量将为空。

        【讨论】:

          【解决方案7】:

          另一种方法是在您的应用程序中全局查看 twig 配置。例如在 Silex 中:

          $app['twig']->addGlobal('someuser', $user);
          

          然后您可以在所有模板中访问该变量:

          Hello, {{someuser.name}}
          

          【讨论】:

          • 好的,在模板内部做同样的事情怎么样?
          【解决方案8】:

          set tagembed 一起使用

          例子:

          parent.twig

          {%  block child %}
          
          {% endblock %}
          
          I say: {{ var }}
          

          child.twig

           {% embed "parent.twig" %}
               {% block child %}
           I child, but i not to fail set    
                   {% endblock %}
              {%  set var='bla' %}
          
           {% endembed %}
          

          【讨论】:

          • 这不会影响父范围
          • 是的,如果您使用扩展但使用embed。查看我的更新
          • 您能否发布一个新的答案,其中包含明确的用法示例,没有错误的变体和奇怪的“NonluxCiBundle:...”,或者更新这个答案,以便我接受?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-22
          • 1970-01-01
          • 2016-04-30
          • 2017-08-05
          • 2013-07-23
          • 2018-11-30
          相关资源
          最近更新 更多