从Twig设置数组元素

148

如何在Twig中设置已存在数组的成员?

我尝试过以下方式:

{% set arr['element'] = 'value' %}

但是我遇到了以下错误:

在......中,出现了意外的标记"value ["的标点符号"(期望的语句块结束)。

12个回答

251

在Twig中没有很好的方法做到这一点。但是,可以使用合并过滤器来实现:

{% set arr = arr|merge({'element': 'value'}) %}
如果element是一个变量,请用方括号将其包围:
{% set arr = arr|merge({(element): 'value'}) %}

@falinsky 你是对的。在Twig中,“.”和“[]”非常相似, 我错了。我查阅了资料并编辑了我的答案。 - Paul
19
我在寻找一种定义动态变量键替代“'element'”的方法。我发现了@LivaX下面的答案。那么,解决方案是{% set arr = arr|merge({(key): 'value'}) %} - Sithu
这太傻了。为什么Twig不允许设置数组值的能力? - Matt Cavanagh
1
@MattCavanagh 因为视图文件(例如Twig)不应包含业务逻辑,所以最终应在模型中处理。 视图确实只需要呈现存在的内容。 不过,在我的情况下,这也是我同意您的原因,我创建了Twig宏来呈现UI对象,例如 {{ UI.button({'type':'submit'}) }},并且所有这些宏都使用| merge设置默认参数,因此有一个逻辑上的需要... - Prof
1
注意:如果您使用数字键(例如在我的情况下,我需要从1到30的键),则键将被强制为基于0的。 - SBO
显示剩余6条评论

84

我遇到了这个问题,但是试图创建整数索引而不是像 'element' 这样的关联索引。

您还需要使用合并过滤器来保护索引键,用()

我遇到了这个问题,但是试图创建整数索引而不是像 'element' 这样的关联索引。

您需要在使用合并过滤器时,也要用()来保护您的索引键:

{% set arr = arr|merge({ (loop.index0): 'value'}) %} 

现在您可以添加自定义索引键,例如 ('element'~loop.index0)


这就是在动态插入键时的实际解决方案,感谢LivaX! - nicolallias

15
如果只需要初始化:
{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}

19
这不是问题的关键点。 - redreinard

5
我尝试了 @LivaX 的答案,但它不起作用,当数组的键是数字时合并无效(https://github.com/twigphp/Twig/issues/789)。
只有当键是字符串时才有效。
我所做的是重新创建另一个数组(`temp`)从初始数组(`t`)中,并将键设置为字符串,例如:
{% for key , value in t%}
{% set temp= temp|merge({(key~'_'):value}) %}
{% endfor %}

t键:0、1、2等。

temp键:0_、1_、2_等。


同样的问题,目前还没有解决方案。 - Timtim

3

您也可以使用以下语法:

{% set myArray = myArray + myArray2 %}

2

我觉得这个问题非常烦人,我的解决方案可能有些传统,不太符合Twig的理念,但我开发了以下解决方案:

$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);

可以按照以下方式使用:
{% set arr = set_element(arr, 'element', 'value') %}

2

如果有人需要在merge无法工作时更新数组,因为它只会将内容添加到数组的末尾而不提供更改现有值的能力,可以参考以下方法。

假设您有一个名为words_array的数组,如下所示:

Object {
 0: "First word"
 1: "Second word"
 2: "Third word"
}

为了更新"第二个单词",你可以按照以下步骤进行:
{% set words_array = {(1): 'New word'} + words_array %}

生成的数组将会是:
Object {
 0: "First word"
 1: "New word"
 2: "Third word"
}

如果您正在使用循环,可以进一步使用loop.index0变量来实现以下操作:

{% for word in words_array %}
  {% if word == 'Second word' %}
    {% set words_array = {(loop.index0): 'New word'} + words_array %}
  {% endif %}
{% endfor %}

2

只需像这样使用{% set arr={'key':'value'} %}(在:后面没有空格),它可以很好地工作。

但是当我在for循环内部使用它时,将其变成数组,它在for范围之外不起作用。

{% 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

1
如果你想在for循环之外使用变量,你需要在for循环之外定义它,参见这里:http://twig.sensiolabs.org/doc/tags/set.html - user2019515
5
这完全是错的。冒号后面的空格不重要。你正在创建新的数组,而不是设置数组中的元素,这才是问题所在。你不能像{{ array }}这样输出一个数组,那会产生错误。这个答案充满了失败和与问题无关的内容。 - redreinard
3
我不明白为什么这个回答有赞,就像之前所说的,几乎所有的内容都是错误的... - lloydimus

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

谢谢这个帖子——我也能够使用(loop.index0)创建一个数组并发送到twig。


1

我有一个多维数组。我能找到的唯一解决方案是创建一个新的临时数组并更新/添加信息,然后将其传递给另一个twig函数。


你能给一个例子吗? - Matoeil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接