#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) }}