Как добавить элемент в массив внутри тега 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-шаблоны в возможность добавления других CSS, JS и т. Д. В файлы HTML без необходимости изменять родительские шаблоны.
Вот вам скрипка Twig Fiddle , с которой вы можете видеть результат.
Обратите внимание, что для других людей, которые ищут ответ на этот вопрос, что я пытаюсь выполнить, возможно использование расширения Twig с функцией, которая добавляет элементы в массив, и вторую функцию для доступа к ней. Пожалуйста, просмотрите мой ответ ниже, который не помечен как правильный, чтобы увидеть способ потенциально сделать это. Мой вопрос, как было сказано, невозможно, как показано DarkBee.
Это невозможно сделать в Twig
, как видно из скомпилированного источника шаблонов, каждый из которых включает шаблоны, получает свою собственную частную область, поскольку массив контекста основан на значении, а не по ссылке
$this->loadTemplate("bar.twig", "main.twig", 2)->display($context);
который затем вызывает doDisplay
в включенном шаблоне
protected function doDisplay(array $context, array $blocks = array())
заметка
Вы можете изменить это поведение, создав собственный Twig_Environment
и Twig_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"); } }
Я нашел способ выполнить то, что искал, однако это не то, что было задано в вопросе, поэтому оно не будет помечено как ответ, но я отправляю быстрый ответ здесь, если кто-то пытается чтобы выяснить, как делать то, что я хотел сделать.
В частности, я пытался включить JS и CSS-файлы из вложенных шаблонов Twig, и то, как я изначально думал, это было с тегом 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>
то не будет никакого вывода.