using a string variable as object name in twig - twig

Is there a way in Twig to use a variable as an object name?
Sth like this: If foo is defined then use the value of foo as the name of the object, if not then use some arbitrary string?
This example is not working but I hope it shows the idea:
{% for block in [foo is defined ? foo : 'someThing'].someProperty %}
So the result if foo is not defined would be
someThing.someProperty
and if foo is the string "someThingElse" it would be
someThingElse.someProperty

Every variable is stored in the special variable _context, chain this with the filter default to take care of foo possibly being undefined,
{% for block in _context[foo|default('someThingElse')].someProperty %}
{{ block }}
{% endfor %}
demo

Related

Convert string into node path

So i am working on a Shopware shop, and i want to read a MediaEntity in Twig. To do so, i am creating a string with the node path (adding the product ID as a variable), which just works fine.
To actually access the MediaEntity, i need to convert this string into a real node path. How do i do that? Or is there maybe another way to create this path?
Here's my code:
{% block component_product_box %}
{{ parent() }}
{% set coverIds = "context.extensions.#{product.coverId}.elements" %}
{{ dump() }}
{% endblock %}
I tried it roughly and something like this should work:
{% set coverIds = _context['extensions'][product.coverId]['elements'] %}
This should solve your problem, I hope.
If you really need to work with a string and "dots" notation, this could be of help:
How to use Twig's attributed function to access nested object properties

Variables concatenation

After about an year of using Smarty i wanted to try Twig.
I am facing a problem concatenating a string and a variable to build dynamically the titles of the page when i switch the language.
In Smarty, the controller passes to the template the variables:
$title_it and $title_en
For the title of the page i do <title>{$title_{$lang}}</title> (where $lang is a global variable) and i can switch the values of the variables when i change the language.
I am not able to replicate this behaviour in Twig.
I tried the following methods without having success:
{{ title_ ~ {{ lang }} }} (I think Twig sees the variable "title_" doesn't exists.
'title_'~{{ lang }} (This prints 'title_it' and not it's content)
Is there a way to keep this logic and continuing to use this approach or do i have to handle the titles of the pages differenly?
Thanks a lot,
Manuel
The _context variable holds all variables in the current context, so you can do:
{{ _context['title_' ~ lang]|default }}
This is basically the same as using the attribute function:
{{ attribute(_context, 'title_' ~ lang)|default }}
I would personally use the former as it's more concise and in my opinion clearer.
The default filter is needed when the environment option strict_variables is set to true (the default value is false, but I prefer to set it to true to avoid accidental problems caused by e.g. typos), otherwise you'll get a Twig_Error_Runtime exception if the variable doesn't exist. For example, if you have variables title_en and title_it but try to output the variable title_de (which doesn't exist), you get that exception with the message Key "title_de" for array with keys "title_en, title_it, lang" does not exist.
A more verbose way to check the existence of a variable is to use the defined test:
{% if _context['title_' ~ lang] is defined %} ... {% endif %}
With the default filter you can also provide a default value:
{{ _context['title_' ~ lang]|default('Default title') }}
If you omit the default value (i.e. you do |default instead of |default('some value')), the default value will be an empty string.
See TwigFiddle
I think here the solutions which can fix your problems.
Controller code:
return $this->render('myTwig.html.twig', array(
'lang'=>'en',
'title_en'=>'English Title',
'title_it'=>'Italian Title'
));
Twig Code:
{% set myVar='title_'~lang %}
{{ attribute(_context, myVar) }}
This will display "English Title" on your page.
Here _context variable is a magic variable in twig where you can find all parameters which you passed from your controller to this twig.
attribute(_context,myVar)
it displays the value from passed parameters key to value.
Hope this will solve your problems.
Thanks
I would change the controller to pre-calculate the language dependent value for title before passing it to the twig template. If you are unable (unwilling) to do that, then ...
<title>{% if lang == 'it' %}{{ title_it }}{% else %}{{ title_en }}{% endif %}</title>

Dynamic variable in Twig, example?

I don't quite understand how the attribute function in Twig works. Can somebody help me with an example?
I have a field in a SQL that is named dynamic. I could be eg "field27", but I don't know the number, the number is saved in radio.id. I would like to do someting like this:
{% for radio in gruppeType.radios %}
<td><!-- value of "field" + radio.id--></td>
{% endfor %}
How can I use field + radio.id as the name of the twig-variable?
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.

Twig: wrap variable in array if not already one, use empty array if missing

I have a variable modifier passed to a few twig templates. I want to be able to not pass it at all, to pass a single string, or to pass an array of strings. I then want to be able to assume it is always an array of strings (possibly empty) in my template code.
At the moment I have at the start of the twig templates
{% set modifier = modifier | default([]) %}
{% if modifier is not iterable %}
{% set modifier = [modifier] %}
{% endif %}
This does what I want, but is there an easier way? It's a lot of code to do something very simple.
You could one-line it with a filter (can't seem to be able to mimic the default filter though)
<?php
$filter = new Twig_SimpleFilter('wrap_array', function ($value) {
return is_array($value) ? $value : [ $value, ];
});
$twig = new Twig_Environment($loader);
$twig->addFilter($filter);
And use it in your template :
{% set foo = foo|default({})|wrap_array %}

Using variables inside Twig functions

I just can't get this to work:
It should set var_2 based on the URL query string value of var_1
The problem is where I call var_1 with {{var_1}}
I've tried various other methods but all throw different errors.
// var_3 set elsewhere
{% set var_1 %}test-{{var_3}}{% endset %}
{% set var_2 = app.request.get({{var_1}}) %}
// need var_2 set for rest of script
You can't use another tag ({{ ... }}) inside a twig tag ({% ... %}). So this is not going to work:
{% set var_2 = app.request.get({{var_1}}) %}
A solution is to just put the variable in function argument:
{% set var_2 = app.request.get(var_1) %}
You don't need to (and often cannot) use {{ }} within twig logic. {{ }} is used to output something to the response. To use a variable in line just name the variable. Also remember that ~ will join strings, but some people don't like using it for some reason!
{% set var_1 = 'test-' ~ var_3 %}
{% set var_2 = app.request.get(var_1) %}

Resources