如何使用 Twig 的属性函数访问嵌套对象属性 [英] How to use Twig's attributed function to access nested object properties

查看:26
本文介绍了如何使用 Twig 的属性函数访问嵌套对象属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用一个 twig 变量来访问另一个 twig 变量的属性,该属性在我找到属性"函数之前不起作用.除了需要访问嵌套属性的情况外,效果很好.当包含属性的变量实际上是对象 + 属性时,它不起作用.例如:

{{ attribute(object1, variable) }} 其中变量 = 名称,工作正常.{{ attribute(object1, variable) }} where variable = object2.name, 不起作用.但是,{{ object1.object2.name }} 的硬编码测试确实有效.

这是我如何做到这一点...我有一个 yaml 配置文件,它由控制器解析并将其传递给名为config"的数组中的 twig.它包含用于定义树枝模板显示内容的参数.

 字段:- 名称:公司名称标签:'ODM'索引视图:真记录视图:真- 名称:位置标签:'位置'索引视图:真记录视图:真实

此外,一组对象(实体)被传递到模板进行渲染.

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

{% 用于数据中的数据 %}<tr>{% 用于 config.fields 中的字段 %}{% if field.indexView %}<td>{{attribute(data, field.name }}</td>{% 万一 %}{% 结束为 %}</tr>{% 结束为 %}

我收到错误:

既不是company.name"属性,也不是company.name()"、getcompany.name()"/iscompany.name()"/hascompany.name()"方法之一或__call()"存在并且在App\Entity\Odm"类中具有公共访问权限.

我想我可以用 '.' 分割 field.name 字符串分隔符,然后对属性进行必要数量的调用,但我真的希望有一个更有说服力的解决方案.我也试过 _context['data.'~ field.name] - 也没有运气.

有什么想法吗?

解决方案

扩展 Nico 的回答>

您可以使用以下代码段实现此目的:

main.twig

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

macro.twig

{% 宏 get_attribute(object, attributes) %}{% 应用无空间 %}{% 设置属性 = 属性|split('.') %}{% 设置值 = 对象 %}{% for attribute in attributes %}{% set value = attribute(value, attribute|trim) 已定义?属性(值,属性|修剪):空%}{% 结束为 %}{{ 价值 }}{% 结束申请 %}{% 宏 %}

演示

<小时>

然而,请注意,如果您尝试为此使用宏并将输出"存储在变量中,请记住宏将返回 Twig_Markup 的实例.这意味着您以后不能使用该值.

示例:

数据

foo:酒吧:foob​​ar: 'Lorem Lipsum'

main.twig

{% set bar = macro.get_attribute(foo, 'bar') %}{{ bar.foobar }} {# <--- 错误原因 `foobar` 不是 `Twig_Markup` 的成员 #}

bar 的真正值实际上甚至不是一个对象或数组,而只是一个字符串,在这个例子中,Array 作为内容

{% set bar = macro.get_attribute(foo, 'bar') %}{{ bar }} {# 输出:数组 #}

I'm trying to use a twig variable to access attributes of another twig variable which was not working until I found the "attributes" function. Works well except in the cases where I need to access nested attributes. It doesn't work when the variable containing the attribute is actually an object + attribute. For example:

{{ attribute(object1, variable) }} where variable = name, works just fine. {{ attribute(object1, variable) }} where variable = object2.name, doesn't work. However, a hard coded test of {{ object1.object2.name }} does work.

Here's how I got to this point...I have a yaml config file that gets parsed by the controller and passes it to twig in an array named 'config'. It contains parameters to define what gets displayed by the twig template.

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

Additionally, an array of objects (entities) gets passed to the template for rendering.

The above "fields.name" is the name of the entity property. I iterate over the array of entities and then iterate over the config.fields array to determine what to display. Here's the twig code:

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

I get the error:

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".

I suppose I could split up the field.name string with a '.' delimiter and then make the necessary number of calls to attribute, but I'm really hoping there's a more eloquent solution. I've also tried _context['data.' ~ field.name] - no luck there either.

Any ideas?

解决方案

To expand on Nico's answer

You could achieve this with the following snippet:

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


However a side note, if you are trying to use a macro for this and store the "output" in a variable, keep in mind that a macro will return an instance of Twig_Markup. This means you can't use the value later on.

An example:

data

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

The real value of bar actually is not even an object or array, but just a string with, in this example, Array as content

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

这篇关于如何使用 Twig 的属性函数访问嵌套对象属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆