如何使用Twig遍历自引用的对象列表并输出嵌套列表

时间:2012-10-01 14:22:25

标签: symfony doctrine-orm twig

  

可能重复:
  Symfony2 Twig unlimited child depth

我想在Twig中循环一个对象列表。该列表具有某种自引用的多对一关系,可以如下所示:

  • 第1项
  • 第2项
    • 第2项1
    • 第2项2
      • 第2项2 1
  • 第3项
    • 项目3 1
  • 第4项

因此实体内的定义如下:

/**
 * @ORM\OneToMany(targetEntity="Item", mappedBy="parent")
 */
private $children;

/**
 * @ORM\ManyToOne(targetEntity="Item", inversedBy="children")
 * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
 */
private $parent;

我知道要创建一个类似于以下内容的列表:

<ul>
    <li>Item 1</li>
    <li>
        Item 2
        <ul>
            <li>Item 2 1</li>
            <li>
                Item 2 2
                <ul>
                    <li>Item 2 2 1</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>
        Item 3
        <ul>
            <li>Item 3 1</li>
        </ul>
    </li>
    <li>Item 4</li>
</ul>

如何做到这一点?

1 个答案:

答案 0 :(得分:2)

在Twig中有几种方法可以做到这一点。一个非常简单的方法是使用递归调用的宏。此宏可以放在与实际输出相同的文件中,并通过以下方式引用:{{ _self.macroname(parameters) }}

请参阅评论以获取详细说明:

<!-- send two variables to the macro: the list of objects and the current level (default/root is null) -->
{% macro recursiveList(objects, parent) %}

    <!-- store, whether there's an element located within the current level -->
    {% set _hit = false %}

    <!-- loop through the items -->
    {% for _item in objects %}

        <!-- get the current parent id if applicable -->
        {% set _value = ( null != _item.parent and null != _item.parent.id ? _item.parent.id : null ) %}

        <!-- compare current level to current parent id -->
        {% if (parent == _value) %}

            <!-- if we have at least one element open the 'ul'-tag and store that we already had a hit -->
            {% if not _hit %}
                <ul class="tab">
                {% set _hit = true %}
            {% endif %}

            <!-- print out element -->
            <li>
                {{ _item.title }}

                <!-- call the macro with the new id as root/parent -->
                {{ _self.recursiveList(objects, _item.id) }}
            </li>
        {% endif %}

    {% endfor %}

    <!-- if there was at least one hit, close the 'ul'-tag properly -->
    {% if _hit %}
        </ul>
    {% endif %}

{% endmacro %}

唯一要做的就是从模板中调用宏一次:

{{ _self.recursiveList(objects) }}

希望,有人发现这也很有用。