我想渲染一棵深度不确定的树(孩子的孩子,孩子的孩子,等等)。我需要递归遍历数组;如何在Twig中做到这一点?
Answers:
我研究了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>
{{_self.menu_links}}
是不好的习惯!在此处阅读注释:宏 在模板中定义要使用的宏时,您可能会想直接通过_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文档中,有关现在要使用的宏_self
,但要在本地导入。
从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>
如果您运行的是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循环变量,该变量在Twig for循环内可用。但是我不确定这个循环变量的范围。
此信息和其他信息可在“ forcu Docu的树枝”上获得!
接受了流感的答案,并做了一些修改:
{# 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>
{{ _self.menu_links(links) }}
。