How can I set member of an already existing array from Twig?
I tried doing it next way:
{% set arr['element'] = 'value' %}
but I got the following error:
Unexpected token "punctuation" of value "[" ("end of statement block" expected) in ...
Just use this like {% set arr={'key':'value'} %}
(with no blank space after the :
), it works well.
But when I use it inside a for loop, to make it an array, it does not work outside of the for scope.
{% for group in user.groups %}
{% set foo={'loop.index0':'group.id'} %}
{% set title={'loop.index0':'group.title'} %}
{{ title }} //it work
{% else %}
{% set foo={'0':'-1'} %}
{% set title={'0':'未分组'} %}
{% endfor %}
{{ title }} //it does not work, saying title is not defined
I have tried @LivaX 's answer but it does not work , merging an array where keys are numeric wont work ( https://github.com/twigphp/Twig/issues/789 ).
That will work only when keys are strings
What I did is recreate another table ( temp
) from the initial table (t
) and make the keys a string , for example :
{% for key , value in t%}
{% set temp= temp|merge({(key~'_'):value}) %}
{% endfor %}
t
keys : 0 , 1 , 2 ..
temp
keys : 0_, 1_ , 2_ ....
{% set links = {} %}
{# Use our array to wrap up our links. #}
{% for item in items %}
{% set links = links|merge({ (loop.index0) : {'url': item.content['#url'].getUri(), 'text': item.content['#title']} }) %}
{% endfor %}
{%
set linkList = {
'title': label,
'links': links
}
%}
{% include '<to twig file>/link-list.twig'%}
Thanks for this thread -- I was also able to create an array with (loop.index0) and send to twig.
I've found this issue very annoying, and my solution is perhaps orthodox and not inline with the Twig philosophy, but I developed the following:
$function = new Twig_Function('set_element', function ($data, $key, $value) {
// Assign value to $data[$key]
if (!is_array($data)) {
return $data;
}
$data[$key] = $value;
return $data;
});
$twig->addFunction($function);
that can be used as follows:
{% set arr = set_element(arr, 'element', 'value') %}
Adding my answer in case anyone needs to update the array when merge
doesn't work because it just appends to the end of an array instead of providing the ability to change an existing value.
Let's say you have an array words_array
like below:
Object {
0: "First word"
1: "Second word"
2: "Third word"
}
In order to update "Second word"
, you can do the following:
{% set words_array = {(1): 'New word'} + words_array %}
The resulting array would be:
Object {
0: "First word"
1: "New word"
2: "Third word"
}
You can take it one step further if you are using a loop and use the loop.index0
variable something like the following:
{% for word in words_array %}
{% if word == 'Second word' %}
{% set words_array = {(loop.index0): 'New word'} + words_array %}
{% endif %}
{% endfor %}
I had this problem sometime ago. Imagine you have an array like this one:
data = {
'user': 'admin',
'password': 'admin1234',
'role': 'admin',
'group': 'root',
'profile': 'admin',
'control': 'all',
'level': 1,
'session': '#DFSFASADASD02',
'pre_oa': 'PRE-OA',
'hepa_oa': 'HEPA-OA',
'pre_ra': 'HEPA-RA',
'hepa_ra': 'HEPA-RA',
'deodor_ra': 'DEODOR-RA'
}
So, you want to show this data in two rows, but remove the password from that list. To this end, split in 2 arrays will be easy with the slice
filter. However, we have to remove the password. For that reason, I'm using this snippet. The idea is to put all the elements lesser than the data
elements size divided by 2. To calculate this we use the filter length
. Now to get the index of the current element we user loop.index
. And finally we *push an associative element in the left or right array. An associative array has two components key
and value
. To reference an array key in twit we operator ()
and we use the merge
filter to push into the array as shown here {% set left_list = left_list|merge({ (key): value }) %}
This is the complete solution.
{% set left_list = {} %}
{% set right_list = {} %}
{% set limit = data|length // 2 %}
{% for key, value in data|cast_to_array %}
{% if key != 'password' %}
{% if loop.index <= limit %}
{% set left_list = left_list|merge({ (key): value }) %}
{% else %}
{% set right_list = right_list|merge({ (key): value }) %}
{% endif %}
{% endif %}
{% endfor %}
{% for key, value in left_list %}
<p>
<label for="{{key}}">{{key}}</label>
<input type="text" name="{{key}}" id="{{key}}" value="{{value}}"
class="text ui-widget-content ui-corner-all">
</p>
{% endfor %}