如何在Twig中渲染树

时间:2011-11-30 13:10:33

标签: loops recursion tree twig

我想渲染一棵深度不确定的树(儿童的孩子等)。我需要递归地遍历数组;我怎么能在Twig中做到这一点?

6 个答案:

答案 0 :(得分:105)

感谢domi27,我玩弄了你的想法并想出了这个。我创建了一个嵌套数组作为我的树,['link'] ['sublinks']为null或另一个更多相同的数组。

<强>模板

要递归的子模板文件:

<!--includes/menu-links.html-->
{% for link in links %}
    <li>
        <a href="{{ link.href }}">{{ link.name }}</a>
        {% if link.sublinks %}
            <ul>
                {% include "includes/menu-links.html" with {'links': link.sublinks} %}
            </ul>
        {% endif %}
    </li>
{% endfor %}

然后在主模板中调用它(有点多余'带'那里的东西):

<ul class="main-menu">
    {% include "includes/menu-links.html" with {'links':links} only %}
</ul>

<强>宏

使用宏可以实现类似的效果:

<!--macros/menu-macros.html-->
{% macro menu_links(links) %}
    {% for link in links %}
        <li>
            <a href="{{ link.href }}">{{ link.name }}</a>
            {% if link.sublinks %}
                <ul>
                    {{ _self.menu_links(link.sublinks) }}
                </ul>
            {% endif %}
        </li>
    {% endfor %}
{% endmacro %}

在主模板中执行以下操作:

{% import "macros/menu-macros.html" as macros %}
<ul class="main-menu">
    {{ macros.menu_links(links) }}
</ul>

希望有所帮助:)

答案 1 :(得分:30)

如果您想在同一模板中使用,您应该使用类似的内容来保持与Twig 2.x兼容

{% macro menu_links(links) %}
    {% import _self as macros %}
    {% for link in links %}
        <li>
            <a href="{{ link.href }}">{{ link.name }}</a>
            {% if link.sublinks %}
                <ul>
                    {{ macros.menu_links(link.sublinks) }}
                </ul>
            {% endif %}
        </li>
    {% endfor %}
{% endmacro %}

{% import _self as macros %}

<ul class="main-menu">
    {{ macros.menu_links(links) }}
</ul>

这扩展了random-coder的答案,并将dr.scre的提示合并到twig documentation about macros,现在使用_self,但在本地导入。

答案 2 :(得分:2)

如果你正在运行PHP 5.4或更高版本,那么Alain Tiemblo对这个问题有一个很好的新解决方案(截至2016年5月):https://github.com/ninsuo/jordan-tree

它是一棵树&#34;用于此目的的标记。标记看起来像这样:

{% tree link in links %}
    {% if treeloop.first %}<ul>{% endif %}

    <li>
        <a href="{{ link.href }}">{{ link.name }}</a>
        {% subtree link.sublinks %}
    </li>

    {% if treeloop.last %}</ul>{% endif %}
{% endtree %}

答案 3 :(得分:1)

首先我想,这可以直接解决 - 但这并不容易。

您需要创建一个逻辑,可能使用php类方法,何时包含一个twig子模板,何时不包括。

<!-- tpl.html.twig -->
<ul>
{% for key, item in menu %}
    {# pseudo twig code #}
    {% if item|hassubitem %}
        {% include "subitem.html.tpl" %}
    {% else %}
        <li>{{ item }}</li>
    {% endif %}
{% endfor %}
</ul>

所以你可以使用特殊的twig loop variable,它可以在一个循环的枝条中找到。但我不确定这个循环变量的范围。

很抱歉只提供一种方法而不是解决方案,但也许我希望我的想法可以帮到你(一点点)。

Twigs "for" Docu可以获得此信息和其他信息!

答案 4 :(得分:0)

接受了流感的回答并对其进行了一些修改:

{# macro #}

{% macro tree(items) %}
    {% import _self as m %}
        {% if items %}
        <ul>
            {% for i in items %}
                <li>
                    <a href="{{ i.url }}">{{ i.title }}</a>
                    {{ m.tree(i.items) }}
                </li>
            {% endfor %}
        </ul>
    {% endif %}
{% endmacro %}

{# usage #}

{% import 'macros.twig' as m %}

{{ m.tree(items) }}

答案 5 :(得分:-1)

这里的答案引导我进入我的解决方案。

我有一个类别实体,自我引用ManyToOne关联(子级的父级)。

/**
 * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
 */
private $parent;

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

在我的树枝模板中,我正在渲染树视图:

<ul>
{% for category in categories %}
    {% if category.parent == null %}
        <li>
            <a href="{{ category.id }}">{{ category.name }}</a>
            {% if category.children|length > 0 %}
            <ul>
            {% for category in category.children %}
                <li>
                    <a href="{{ category.id }}">{{ category.name }}</a>
                </li>
            {% endfor %}
            </ul>
            {% endif %}
        </li>
    {% endif %}
{% endfor %}
</ul>