如何在树枝上渲染一棵树


89

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

Answers:


117

我研究了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 %}

然后在主模板中调用此代码(那里有一些多余的“ with”东西):

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

9
非常感谢!如果要在同一模板中使用宏,则可以使用{{ _self.menu_links(links) }}
流感

谢谢,想到这一点使我的大脑受伤,但是您的回答很合理。
azzy81

我的项目有一个问题并提出了意见。子注释(子链接)也包含在主集合(链接)中。所以在包含之前,我必须检查注释中是否有“父”条目。
Jevgeni Smirnov

4
使用{{_self.menu_links}}不好的习惯!在此处阅读注释: 在模板中定义要使用的宏时,您可能会想直接通过_self.input()而不是导入宏来调用该宏。即使看起来可行,这也只是当前实现的副作用,在Twig 2.x中将不再起作用。您应该在本地再次在本地导入宏menu_links
dr.scre 2014年

35

树枝2.0-2.11

如果要在同一模板中使用,则应使用类似于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文档中,有关现在要使用的_self,但要在本地导入。

树枝> = 2.11

Twig 2.11开始,您可以省略{% import _self as macros %},因为内联宏会自动导入到_self命名空间下(请参阅Twig公告:自动宏导入):

{# {% import _self as macros %} - Can be removed #}

<ul class="main-menu">
    {{ _self.menu_links(links) }} {# Use _self for inlined macros #}
</ul>

2

如果您运行的是PHP 5.4或更高版本,Alain Tiemblo会针对此问题提供一个很棒的新解决方案(截至2016年5月):https : //github.com/ninsuo/jordan-tree

这是一个“树”标签,可用于此确切目的。标记看起来像这样:

{% 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 %}

1
您不能将其他变量传递给subtree。就我而言,代码需要知道是否会有更多的子代,并将级别数传递给宏,以便可以执行<div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">。计算此值将需要第二次迭代当前级别,以捕获是否有任何子级。
chx

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循环变量,该变量在Twig for循环内可用。但是我不确定这个循环变量的范围。

此信息和其他信息可在“ forcu Docu的树枝”上获得


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

-1

这里的答案将我引向我的解决方案。

我有一个类别实体,具有自我引用的多对一关联(对于孩子而言是父)。

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

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

在我的Twig模板中,我正在渲染树状视图,如下所示:

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

如果您具有多个级别的类别层次结构怎么办?
pmoubed
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.