Обновление свойств объекта в twig

#php #twig

#php #twig

Вопрос:

Есть ли способ обновить свойство объекта в twig?

В twig передается объект, подобный следующему:

 object
   property1
   property2
  

Я хотел бы обновить свойство1 следующим образом:

 {% set object.property1 = 'somenewvalue' %}
  

Приведенный выше код не работает, но возможно ли сделать что-то подобное в twig? Если нет, есть ли способ написать расширение или макрос для этого?

Комментарии:

1. Пожалуйста, проигнорируйте мой ответ ниже, он очень устарел и больше не должен быть принятым ответом. К сожалению, я не могу удалить его, поскольку это принятый ответ.

2. @rdjs Спасибо, что дали мне знать! Я поменял принятый ответ!

3. Принятый ответ работает только для массивов и хэшей, а не для объектов.

4. Я создал проблему по этому поводу: github.com/twigphp/Twig/issues/2768

5. Согласно symfony crew, попытка сделать это — «деловая логика в twig», чего следует избегать. См. github.com/twigphp/Twig/issues/2768#issuecomment-442368654

Ответ №1:

Ответ от 2013

Вы можете сделать это, объединив объекты:

 {% set object = object|merge({'property1': 'somenewvalue'}) %}
  

Обновление с 2023 года

Я не знаю, с какой версии twig это решение больше не работает. Теперь вы можете создать объект только с новым именем:

 {% set data = {foo:1} %}
{% set updated = data|merge({ bar: 2 }) %}

foo: {{ updated.foo }} {# Produces “foo: 1” #}
bar: {{ updated.bar }} {# Produces “bar: 2” #}
  

Комментарии:

1. 1 отличный собственный способ сделать это. Идеально подходит для одного сценария использования.

2. Итак, почему это принятый ответ? Это работает только в некоторых версиях Twig?

3. Это не должно быть принятым ответом, поскольку он не отвечает на вопрос «как обновить свойства объекта».

4. На самом деле это не должно быть принятым ответом — согласно выводу ошибки Twig: фильтр слияния работает только с массивами или «проходимыми», получил «объект» в качестве первого аргумента. Приведенный ниже ответ @Baishu работает для моего варианта использования объекта

5. Боюсь, это работает для массивов, а не для объектов. Это вводящий в заблуждение ответ.

Ответ №2:

В Twig есть тег do, который позволяет вам это делать.

 {% do foo.setBar(value) %}
  

Ответ №3:

Возможный способ задать свойство — создать метод в объекте, который фактически создает новые свойства:

 class Get extends StdClass 
  {

    protected function setProperty($name,$value = null)
    {
    $this->$name = $value;
    }

  }
  

Комментарии:

1. Мне пришлось установить этот метод общедоступным, но это действительно хорошее решение

2. Что? И как в мире вы вызываете это из Twig?

3. @BrunoSantos object.setProperty("propertyName", 3) это установит / создаст propertyName значение 3

4. в twig: {% do object.setProperty("propertyName", 3) %}

Ответ №4:

У меня была такая же проблема в моем шаблоне меню knp. Я хотел отобразить альтернативное поле с label блоком, не дублируя его. Конечно, базовому объекту нужен установщик для свойства.

 {%- block nav_label -%}
    {%- set oldLabel = item.label %}
    {%- set navLabel = item.getExtra('nav_label')|default(oldLabel) %}
    {{- item.setLabel(navLabel) ? '' : '' }}
    {{- block('label') -}}
    {{- item.setLabel(oldLabel) ? '' : '' }}
{%- endblock -%}
  

Комментарии:

1. вместо {{- xx.f() ? '' : '' }} , используйте this: {% do xx.f() %} , он никогда ничего не печатает. twig.symfony.com/doc/2.x/tags/do.html

Ответ №5:

Если вашим свойством является array (object-> property[‘key’]), вы можете сделать что-то вроде этого:

 {% set arr = object.property|merge({"key":['some value']}) %}
{{ set(object, 'property', arr) }}
  

Это эквивалентно:

 this->property['key'][] = 'some value';
  

Комментарии:

1. Вы сэкономили мое время 🙂

2. опять же, только yii2

Ответ №6:

 {{ set(object, 'property', value) }}