Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
555 views
in Technique[技术] by (71.8m points)

php - Twig: Add item to array from within an included template

How can you add an item to an array within an include tag when the array is defined in the main file?

Please note this question is distinctly different from other array questions in Twig because I'm trying to modify the value from within an included template in the main file.

For example:

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}}

Currently the output from main.twig gives me only the initial test1 item, and not the combination of the two which test.twig is trying to modify.

I may have to utilize an added function. The goal here is basically to allow included templates the ability to add other CSS, JS, etc, in HTML files without having to modify the parent templates.

Here is a Twig Fiddle for you to play with which shows the output.

Please note for other people looking for an answer to this question, what I was attempting to accomplish is possible utilizing a Twig extension with a function that adds items to the array, and a second function to access it. Please view my answer below, that is not marked as correct, to see a way to potentially do this. My question, as stated, is impossible, as shown by DarkBee.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This can't be done in Twig, as seen in the compiled source of the templates each included templats get his own private scope as the context array is based by value and not by reference

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

which then calls doDisplay in the included template

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

note

You could alter this behaviour by creating your own Twig_Environment and Twig_Template but a quick look shows me that there are quite some functions you'd need to override.


main.twig

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

Foo in foo: {{ foo }}

bar.twig

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

Source 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");
    }
}

Source 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");
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...