Twig:从包含的模板

时间:2017-02-09 23:05:16

标签: php arrays symfony twig

当在主文件中定义数组时,如何将项添加到include标记内的数组中?

请注意,这个问题与Twig中的其他数组问题明显不同,因为我试图修改主文件中包含的模板中的值。

例如:

main.twig

{% set includes = ["test1"] %}
{% include "test.twig" %}
{{includes|json_encode}} {# "How do I make this `includes` contain the "test2" array item?" #}

test.twig

{% set includes = includes|merge(["test2"]) %}
{{includes|json_encode}}

目前main.twig的输出只给我初始test1项,而不是test.twig试图修改的两者的组合。

我可能必须使用附加功能。这里的目标基本上是允许include d模板在HTML文件中添加其他CSS,JS等,而无需修改父模板。

以下是您可以使用的Twig Fiddle来显示输出。

  

请注意,对于寻找这个问题答案的其他人,我试图完成的是使用带有向数组添加项目的功能的Twig扩展,以及第二个访问它的功能。请查看下面的答案,该答案未标记为正确,以查看可能执行此操作的方法。如上所述,我的问题是不可能的,如DarkBee所示。

2 个答案:

答案 0 :(得分:1)

这不能在Twig中完成,如模板的编译源中所示,每个包含的templats都有自己的私有范围,因为上下文数组是基于值而不是引用

$this->loadTemplate("bar.twig", "main.twig", 2)->display($context);

然后在包含的模板中调用doDisplay

protected function doDisplay(array $context, array $blocks = array())

注意

可以通过创建自己的Twig_EnvironmentTwig_Template来改变这种行为,但快速浏览一下我会发现你需要覆盖一些功能

main.twig

{% set foo = 'bar' %}
{% include 'bar.twig' %}

Foo in foo: {{ foo }}

bar.twig

{% set foo = 'foo' %}
Foo in bar: {{ foo }}

来源main.twig     

/* main.twig */
class __TwigTemplate_4ba23e628289532331bb5889dca1a4ec57774924d21a760ca6fe6f575a3978b5 extends Twig_Template
{
    public function __construct(Twig_Environment $env)
    {
        parent::__construct($env);

        $this->parent = false;

        $this->blocks = array(
        );
    }

    protected function doDisplay(array $context, array $blocks = array())
    {
        // line 1
        $context["foo"] = "bar";
        // line 2
        $this->loadTemplate("bar.twig", "main.twig", 2)->display($context);
        // line 3
        echo "
Foo in foo: ";
        // line 4
        echo twig_escape_filter($this->env, ($context["foo"] ?? null), "html", null, true);
    }

    public function getTemplateName()
    {
        return "main.twig";
    }

    public function isTraitable()
    {
        return false;
    }

    public function getDebugInfo()
    {
        return array (  26 => 4,  23 => 3,  21 => 2,  19 => 1,);
    }

    public function getSourceContext()
    {
        return new Twig_Source("", "main.twig", "/fuz/twigfiddle.com/files/environment/k85WDdymIFgSoXLc/twig/main.twig");
    }
}

来源bar.twig

<?php

/* bar.twig */
class __TwigTemplate_16789decfbb837d4631acf2e648380c0658722c50a0b53184b3f3c5f68f9b0ae extends Twig_Template
{
    public function __construct(Twig_Environment $env)
    {
        parent::__construct($env);

        $this->parent = false;

        $this->blocks = array(
        );
    }

    protected function doDisplay(array $context, array $blocks = array())
    {
        // line 1
        $context["foo"] = "foo";
        // line 2
        echo "Foo in bar: ";
        echo twig_escape_filter($this->env, ($context["foo"] ?? null), "html", null, true);
    }

    public function getTemplateName()
    {
        return "bar.twig";
    }

    public function isTraitable()
    {
        return false;
    }

    public function getDebugInfo()
    {
        return array (  21 => 2,  19 => 1,);
    }

    public function getSourceContext()
    {
        return new Twig_Source("", "bar.twig", "/fuz/twigfiddle.com/files/environment/k85WDdymIFgSoXLc/twig/bar.twig");
    }
}

答案 1 :(得分:0)

我找到了一种方法来完成我想要的东西,但问题并不是问题,所以它不会被标记为答案,但我发布的是如果其他人试图弄清楚如何做我想做的事情,请在这里快速回答。

具体来说,我试图在嵌套的Twig模板中包含JS和CSS文件,而我最初想要的方式是使用merge标记,但是,如标记答案中的DarkBee所示,这是不可能的。

作为替代方案,我能够创建一个扩展程序,允许我执行我在全球范围内寻找的内容,使用尽可能多的不同阵列名称:

class arrayDefinitionExtension extends \Twig_Extension
{
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('addToArray', [$this, "addToArray"]),
            new \Twig_SimpleFunction('getArray', [$this, "getArray"]),
        );
    }

    private $arrays = [];

    public function addToArray($name, $val) {
        $this->arrays[$name][] = $text;
        return "";
    }

    public function getArray($name) {
        if(isset($this->arrays[$name])) {
            return $this->arrays[$name];
        } else {
            return [];
        }
    }
}

用法:

base.php

$loader = new \Twig_Loader_Filesystem('/path/to/templates');
$twig = new \Twig_Environment($loader);
$twig->addExtension(new \arrayDefinitionExtension());

base.twig

{% block content %}
{% endblock %}

{% set includes = getArray("includes") %}
{% for include in includes %}
    <script src="{{include}}" type="application/javascript"></script>
{% endfor %}

main.twig

{% extends "base.twig" %}
{% block content %}
    {% include "test.twig" %}
{% endblock %}

test.twig

{% do addToArray("includes", "path/to/some/file.js") %}
  

请注意,这是顺序的,因此如果您在打印content标签后放置了<script>块,则无法输出任何内容。