如何使用Twig的属性函数访问嵌套对象的属性

时间:2019-05-15 15:41:19

标签: php symfony twig

我正在尝试使用一个twig变量访问另一个twig变量的属性,直到我找到“属性”功能,该变量才起作用。除了在需要访问嵌套属性的情况下,效果很好。当包含属性的变量实际上是一个对象+属性时,它将不起作用。例如:

{{ attribute(object1, variable) }},其中变量= name,可以正常工作。 {{ attribute(object1, variable) }},其中变量= object2.name,不起作用。 但是,可以对{{ object1.object2.name }}进行硬编码测试。

这就是我到此为止的方式...我有一个yaml配置文件,该文件由控制器解析,并将其传递给名为“ config”的数组中的twig。它包含用于定义树枝模板显示的内容的参数。

fields:
  - name: company.name
    label: 'ODM'
    indexView: true
    recodrdView: true
  - name: location
    label: 'Location'
    indexView: true
    recordView: true

另外,将对象(实体)的数组传递到模板进行渲染。

以上“ fields.name”是实体属性的名称。我遍历实体数组,然后遍历config.fields数组以确定要显示的内容。这是树枝代码:

{% for data in datum %}
    <tr>
    {% for field in config.fields %}
        {% if field.indexView %}
            <td>{{ attribute(data, field.name }}</td>       
        {% endif %}
    {% endfor %}
    </tr>
{% endfor %}

我得到了错误:

Neither the property "company.name" nor one of the methods "company.name()", "getcompany.name()"/"iscompany.name()"/"hascompany.name()" or "__call()" exist and have public access in class "App\Entity\Odm".

我想我可以用'。'分隔field.name字符串。分隔符,然后对属性进行必要数量的调用,但是我真的希望有一个更雄辩的解决方案。我也尝试过_context ['data。' 〜field.name]-那里也没有运气。

有什么想法吗?

4 个答案:

答案 0 :(得分:0)

只需考虑属性的命名:是一个名为company.name的单个属性,那么您可以通过这种方式访问​​它。如果有一个属性company本身拥有另一个名为name的属性,那么您将无法使用company.name来访问它。

您可以尝试的方法:编写一个使用字段名的树枝宏,将其拆分为点,如果其余部分仍包含点,则递归调用自身。

答案 1 :(得分:0)

您应该嵌套对attribute的呼叫。

例如要获得与object1.object2.name相同的功能,您可以使用:

{{ attribute(attribute(object1, 'object2'), 'name') }}

答案 2 :(得分:0)

扩展Nico的答案

您可以使用以下代码段实现这一目标:

main.twig

{% import 'macro.twig' as macro %}
{{ macro.get_attribute(foo, 'bar.foobar') }}

macro.twig

{% macro get_attribute(object, attributes) %}
    {% apply spaceless %}
    {% set attributes = attributes|split('.') %}

    {% set value = object %}
    {% for attribute in attributes %}
        {% set value = attribute(value, attribute|trim) is defined ? attribute(value, attribute|trim) : null %}
    {% endfor %}
    {{ value }}
    {% endapply %}    
{% endmacro %}

demo


不过,请注意,如果您尝试为此使用宏并将“输出”存储在变量中,请记住,宏将返回Twig_Markup的实例。这意味着您以后无法使用该值。

一个例子:

数据

foo:
    bar:
        foobar: 'Lorem Lipsum'

main.twig

{% set bar = macro.get_attribute(foo, 'bar') %}
{{ bar.foobar }} {# <--- error cause `foobar` is not a member of `Twig_Markup` #}

bar的实际值实际上甚至不是对象或数组,而只是一个以Array作为内容的字符串

{% set bar = macro.get_attribute(foo, 'bar') %}
{{ bar }} {# output: Array #}

答案 3 :(得分:0)

如果您使用的是 Twig >= 2.10,则可以使用 reduce() 过滤器:

{{ field.name|split('.')|reduce((carry, v) => carry ? attribute(carry, v) : null, data) }}