【发布时间】:2011-11-30 13:10:32
【问题描述】:
我想渲染一棵深度不确定的树(children of children 等)。我需要递归地遍历数组;我如何在 Twig 中做到这一点?
【问题讨论】:
我想渲染一棵深度不确定的树(children of children 等)。我需要递归地遍历数组;我如何在 Twig 中做到这一点?
【问题讨论】:
我玩弄了domi27's idea 并想出了这个。我做了一个嵌套数组作为我的树,['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>
【讨论】:
{{ _self.menu_links(links) }}。
{{_self.menu_links}} 是一种不好的做法!在此处阅读注释:macro 当您在要使用它的模板中定义宏时,您可能会想通过 _self.input() 直接调用该宏,而不是导入它;即使看起来可行,这也只是当前实现的副作用,它在 Twig 2.x 中不再有效。您应该再次在本地导入宏在menu_links
如果你想在同一个模板中使用宏,你应该使用类似这样的东西来保持与 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,但在本地导入。
从 Twig 2.11 开始,您可以省略 {% import _self as macros %},因为内联宏会在 _self 命名空间下自动导入(请参阅 Twig announcement: Automatic macro import):
{# {% import _self as macros %} - Can be removed #}
<ul class="main-menu">
{{ _self.menu_links(links) }} {# Use _self for inlined macros #}
</ul>
【讨论】:
如果您运行的是 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 %}
【讨论】:
subtree。在我的情况下,代码需要知道是否会有更多的孩子,并将级别数传递给宏,以便它可以执行<div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">。计算这个需要第二次迭代当前关卡来捕捉是否有任何孩子。
首先我认为这可能会以一种简单的方式解决,但并不是那么容易。
您需要创建逻辑,可能使用 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,它在 Twig for 循环中可用。但我不确定这个 loop 变量的范围。
此信息和其他信息可在 Twigs "for" Docu! 上获得!
【讨论】:
取flu's answer并稍作修改:
{# 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) }}
【讨论】:
这里的答案引导我找到我的解决方案。
我有一个具有自引用多对一关联(父对子)的类别实体。
/**
* @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>
【讨论】: