Установка элемента массива из Twig


126

Как я могу установить член уже существующего массива из Twig?

Я попробовал сделать это следующим образом:

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

но я получил следующую ошибку:

Неожиданный знак «пунктуация» значения «[» (ожидается «конец блока оператора») в ...

Ответы:


211

В Twig нет хорошего способа сделать это. Однако это возможно с помощью фильтра слияния:

{% set arr = arr|merge({'element': 'value'}) %}

«.» - утверждение такое же, как «[]», так что это не решение
фалинский

@falinsky Ты прав. .и []очень похожи в Twig, и я ошибался. Я посмотрел и отредактировал свой ответ.
Пол

17
Я искал способ определить ключ динамической переменной вместо 'element'. Я нашел ответ @LivaX ниже. Так бы и было {% set arr = arr|merge({(key): 'value'}) %}.
Ситху

Это так глупо. Почему twig не позволяет устанавливать значения массива?
Мэтт Кэвэна,

1
@MattCavanagh, поскольку файлы представлений (например, Twig) не должны содержать бизнес-логику, в конечном итоге это должно быть обработано в модели. Представление действительно должно просто отображать то, что есть. Проблема в моем случае, и почему я также согласен с вами, заключается в том, что я создаю макросы веточки для рендеринга объектов пользовательского интерфейса, например. {{ UI.button({'type':'submit'}) }}и все эти макросы используют | merge для установки параметров по умолчанию, так что в этом есть логическая необходимость ...
Prof83 02

80

Я столкнулся с этой проблемой, но пытался создать целочисленные индексы вместо ассоциативного индекса, такого как «элемент».

Вам также необходимо защитить свой индексный ключ с ()помощью фильтра слияния:

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

Теперь вы можете добавить собственный индексный ключ, например ('element'~loop.index0)


Это реальное решение, когда вы пытаетесь динамически вставлять ключи, спасибо LivaX!
nicolallias

18

Если требуется только инициализация:

{% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %}

9
Не в этом был вопрос.
redreinard

2

Я пробовал ответить @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_ ....


Та же проблема, решения пока нет.
TyrionGraphiste

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) и отправить его в ветку.


1

Я нашел эту проблему очень раздражающей, и мое решение, возможно, является ортодоксальным и не соответствует философии 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')%}


1

Просто используйте это как {% 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, см. Здесь: twig.sensiolabs.org/doc/tags/set.html
user2019515

5
Это все неправильно. Пробел после двоеточия значения не имеет. Вы создаете новые массивы, а не устанавливаете элемент в массиве, о котором шла речь. Вы не можете вывести такой массив, как {{array}}, это вызовет ошибку. Этот ответ полон неудач и не имеет отношения к заданному вопросу.
redreinard

3
Я не понимаю, почему у этого есть апвоуты, как указано выше, в этом «ответе» почти все неверно ...
MariusJP

0

У меня был многомерный массив. Единственное решение, которое я смог найти, - это создать новый временный массив и обновить / добавить информацию, которая затем была передана другой функции веточки.


0

Некоторое время назад у меня была эта проблема. Представьте, что у вас есть такой массив:

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

Итак, вы хотите отобразить эти данные в двух строках, но удалите пароль из этого списка. С этой целью с помощью sliceфильтра будет легко разделить на 2 массива . Однако мы должны удалить пароль. По этой причине я использую этот фрагмент. Идея состоит в том, чтобы поместить все элементы меньше, чем dataразмер элементов, разделенный на 2. Чтобы вычислить это, мы используем фильтр length. Теперь, чтобы получить индекс текущего пользовательского элемента loop.index. И, наконец, мы * вставляем ассоциативный элемент в левый или правый массив. Ассоциативный массив состоит из двух компонентов keyи value. Чтобы ссылаться на ключ массива в twit, мы оператор, ()и мы используем mergeфильтр для вставки в массив, как показано здесь{% set left_list = left_list|merge({ (key): value }) %}

Это полное решение.

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

0

Вы также можете использовать следующий синтаксис:

{% set myArray = myArray + myArray2 %}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.