0

I'm trying to override a variable in the included template.

Can I do this in a Symfony3 & Twig?

My twig template looks like this:

{% set foo = 'bar' %}
{% include 'first.html.twig' %}
{% include 'second.html.twig' %}

// first.html.twig  
{{ foo }}
{% set foo = 'second' %}

// second.html.twig  
{{ foo }}

I get such a result:

bar bar

But I expect:

bar second

3
  • 1
    i guess it is not possible. Templates are designed to receive variables just to render them and not more than that. Instead you should put that logic inside your controller as controllers are made to collect data and pass that data to the view Commented Oct 11, 2017 at 22:34
  • 1
    To achieve what you want you'd need to include second.html.twig within first.html.twig. Variables don't bubble back upwards. Commented Oct 12, 2017 at 1:13
  • Have a look at this answer for an alternative solution Commented Oct 12, 2017 at 5:45

4 Answers 4

1

The following Twig code:

{% set a = 42 %}
{{ include("first.twig") }}

Will be compiled to this one:

 // line 1
 $context["a"] = 42;
 // line 2
 echo twig_include($this->env, $context, "first.twig");

And twig_include prototype is:

# lib/Twig/Extension/Core.php
function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)

So variables are passed by copy, not by reference in included templates. Thus your changes in included templates won't be reflected to including templates.

Moreover, since Twig 2.0, you can't call TwigEnvironment::addGlobal once twig runtime is initialized, so you can't glitch using simple extensions.

All in all, you can understand that if you need to update variables cross templates, it means some template contains business logic and Twig isn't build for that. You need to prepare the whole context in controllers.

Sign up to request clarification or add additional context in comments.

3 Comments

update variables cross templates - Not always. creating an array with required dependencies, like javascript files could be a valid strategy to work with cross-template variables
What do you mean? I don't really understand your example.
Code-example of what I mean over here
0

Alternatively you may call a PHP class method from TWIG. Example of a page-counter needed when generating a pdf.

Custom class :

class PageCounter 
{
    private $pageNumber = 0;

    public function incrementPageCounter()
    {
        $this->pageNumber ++;

        return $this->pageNumber;
    }
}

Controller:

....
$twigVariables = [
        ...
        'pageCounter' => new PageCounter()
    ];

return $this->render('template.html.twig', $twigVariables);

Twig template (object pageCounter available from any included template)

{{ pageCounter.incrementPageCounter() }} / {{totalPages}}

Comments

0

You just need to do the check and override the variable with another variable :))

{% if name is defined %}
   {% set foo = name %}
{% else %}
   {% set foo = 'bar' %}
{% endif %}
{% include 'first.html.twig' %}
{% include 'second.html.twig' %}

// first.html.twig  
{% set name = 'first' %}

// second.html.twig  
{% set name = 'second' %}

Comments

-1

Why not override your variable with your include tag/function like :

{% include 'first.html.twig' with {'foo': 'second'} %}

or :

{ include('first.html.twig', {foo: 'second'}) }}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.