How to Access Dynamic Variable Names in Twig

Dynamic variable in Twig, example?

You can build the field name with a variable, then use it in the attribute function to access the data within the object/array. As example:

{% set fieldName = "field" ~ radio.id %}

{{ attribute(gruppeType, fieldName) }}

A working example can be seen in this twigfiddle

Hope this helps.

Variable name from _multiple_ variables in Twig

You just concat them all?

{% set long_variable_name_here = 'foo' %}


{% set long = 'long' %}
{% set variable = 'variable' %}
{% set name = 'name' %}
{% set here = 'here' %}


{{ attribute(_context, long~'_'~variable~'_'~name~'_'~here) }}

demo


{% set var_1_1_tax_class_id = 0 %}

<select name="var_{{ geo_zone['geo_zone_id'] | default(1) }}_{{ group['group_id']|default(1) }}_tax_class_id">
<option value="0"{{ attribute(_context, 'var_'~geo_zone['geo_zone_id']|default(1)~'_'~group['group_id']|default(1)~'_tax_class_id') | default(-1) == 0 ? ' checked' }}>{{ text_none | default('text') }}</option>
</select>

Twig use dynamic variables


    {% set foobar = workday ~ "_morning_availability" %}

{{ workday }} : {{ attribute(user, foobar) }}

Dynamic variable name TWIG

Try using attribute function as example:

{{ form_row(attribute(propForm, ("in"~i) ) ) }}

PS: remember to use the parenthesis to generate the attribute name

Dynamic twig variable names

I know this syntax works

{% render "..." with {(key): value} %}

Did you try the following syntax? As of March, Friday 22nd this syntax didn't work so you need to use a work around.

{% set (key) = value %}

An alternative to that would be to include a template and pass and form.vars.attr.

{% include "YourAwesomeBundle:Controller:template.html.twig" with form.vars.attr %}

You can also merge form.vars.attr with another array using the merge function.

{% set vars = {} %}
{% set vars = vars|merge(form.vars.attr) %}
{% include "YourAwesomeBundle:Controller:template.html.twig" with vars %}

Within the included template you will be able to use the variable em and group.

How to set a variable name with dynamic variables?

Like @DarkBee mentioned, you can't do this in vanilla Twig. But you can create quite a simple extension – notice that $context needs to be passed by reference:

class MyTwigExtension extends Twig_Extension {
public function getFunctions() {
return [
new Twig_Function('set', [$this, 'set'], ['needs_context' => true]),
];
}

public function set(&$context, $name, $value) {
$context[$name] = $value;
}
}
$twig->addExtension(new MyTwigExtension());

Then in Twig you can do:

{{ dump() }}
{% do set('foo' ~ 1, 'bar') %}
{{ dump() }}

The above will print:

array(0) {
}

array(1) {
["foo1"]=>
string(3) "bar"
}

But note that a for loop has its own context. So if you do this:

{% set foo = 'bar' %}

Before loop:
{{ dump() }}

{% for i in 0..2 %}
{%- do set('foo' ~ i, 'iteration ' ~ i) %}
{%- if loop.last %}
{{- 'Inside loop (last iteration):\n' }}
{{- loop.last ? dump() }}
{% endif %}
{% endfor %}

After loop:
{{ dump() }}

You get this – notice the _parent array which represents the "parent" context outside of the loop:

Before loop:
array(1) {
["foo"]=>
string(3) "bar"
}


Inside loop (last iteration):
array(9) {
["foo"]=>
string(3) "bar"
["_parent"]=>
array(1) {
["foo"]=>
string(3) "bar"
}
["_seq"]=>
array(3) {
[0]=>
int(0)
[1]=>
int(1)
[2]=>
int(2)
}
["loop"]=>
array(8) {
["parent"]=>
array(1) {
["foo"]=>
string(3) "bar"
}
["index0"]=>
int(2)
["index"]=>
int(3)
["first"]=>
bool(false)
["revindex0"]=>
int(0)
["revindex"]=>
int(1)
["length"]=>
int(3)
["last"]=>
bool(true)
}
["i"]=>
int(2)
["_key"]=>
int(2)
["foo0"]=>
string(11) "iteration 0"
["foo1"]=>
string(11) "iteration 1"
["foo2"]=>
string(11) "iteration 2"
}


After loop:
array(1) {
["foo"]=>
string(3) "bar"
}

You can overcome this limitation in three ways. First is to initialize the variables before the for loop (notice that foo0 is left as null because the loop starts at 1, and that foo3 won't be in the global context because it hasn't been initialized):

{% set foo0 = null %}
{% set foo1 = null %}
{% set foo2 = null %}

{% for i in 1..3 %}
{% do set('foo' ~ i, 'iteration ' ~ i) %}
{% endfor %}

{{ dump() }}

The above will print:

array(3) {
["foo0"]=>
NULL
["foo1"]=>
string(11) "iteration 1"
["foo2"]=>
string(11) "iteration 2"
}

The second way is to modify the extension's set method to check whether $context contains a key _parent:

public function set(&$context, $name, $value) {
$context[$name] = $value;

if (array_key_exists('_parent', $context)) {
$this->set($context['_parent'], $name, $value);
}
}

Then even nested for loops aren't a problem:

{% for i in 1..2 %}
{% for j in 3..4 %}
{% do set('foo' ~ i ~ j, i ~ ' and ' ~ j) %}
{% endfor %}
{% endfor %}

{{ dump() }}

The above will print:

array(4) {
["foo13"]=>
string(7) "1 and 3"
["foo14"]=>
string(7) "1 and 4"
["foo23"]=>
string(7) "2 and 3"
["foo24"]=>
string(7) "2 and 4"
}

The third way is to keep the extension's set method intact and create a new method, e.g. set_global:

class MyTwigExtension extends Twig_Extension {
public function getFunctions() {
return [
new Twig_Function('set', [$this, 'set'], ['needs_context' => true]),
new Twig_Function('set_global', [$this, 'set_global'], ['needs_context' => true]),
];
}

public function set(&$context, $name, $value) {
$context[$name] = $value;
}

public function set_global(&$context, $name, $value) {
$context[$name] = $value;

if (array_key_exists('_parent', $context)) {
return $this->set_global($context['_parent'], $name, $value);
}
}
}
$twig->addExtension(new MyTwigExtension());

Then you can use set to set variables in the current context (e.g. in the context of a for loop) or set_global to set "global" variables (in the context of the file). You can use both methods inside for loops to set new values to already initialized variables.

Access variable inside a loop and variable in Twig

Yes. The _context variable holds all variables in the current context. You can access its values with the bracket notation or using the attribute function:

{% for i in 0..10 %}
{% if _context['content_' ~ i ~ '_raw'] == 2 %}
...
{% endif %}

{# or #}

{% if attribute(_context, 'content_' ~ i ~ '_raw') == 2 %}
...
{% endif %}
{% endfor %}

I have written more details about this here: Symfony2 - How to access dynamic variable names in twig

Also, instead of writing 'content_' ~ i ~ '_raw' (tilde, ~, is string concatenation operator), you can also use string interpolation:

"content_#{i}_raw"


Related Topics



Leave a reply



Submit