Я хотел бы сделать дерево с неопределенной глубиной (дети детей детей и т.д.). Мне нужно петлю через массив рекурсивно; как я могу это сделать в Twig?
Как сделать дерево в Twig
Ответ 1
Спасибо domi27, я играл с вашей идеей и придумал это. Я сделал вложенный массив как мое дерево, ['link'] ['sublinks'] является нулевым или другим массивом более одного и того же.
Шаблоны
Файл подтаблицы для рекурсии:
<!--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 %}
Затем в главном шаблоне назовите это (kinda redundant 'with' stuff there):
<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>
Надеюсь, это поможет:)
Ответ 2
Если вы хотите использовать макрос в том же шаблоне, вы должны использовать что-то вроде этого, чтобы оставаться совместимым с 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
ответ random-coder
и включает подсказку dr.scre
к документации ветки о макросах, чтобы теперь использовать _self
но импортировать локально.
Изменить (2019-07-01):
Начиная с Twig 2.11, вы можете опустить {% import _self as macros %}
, поскольку встроенные макросы автоматически импортируются в пространство имен _self
(см. _self
Twig: Автоматический импорт макросов):
{# {% import _self as macros %} - Can be removed #}
<ul class="main-menu">
{{ _self.menu_links(links) }} {# use _self for inlined macros #}
</ul>
Ответ 3
Если вы используете PHP 5.4 или новее, есть замечательное новое решение (по состоянию на май 2016 года) по этой проблеме Алена Тимбло: 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 %}
Ответ 4
Сначала я подумал, что это можно решить просто, но это не так просто.
Вам нужно создать логику, может быть, с помощью метода класса 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, которая доступна внутри цикла twig for. Но я не уверен в объеме этой переменной цикла.
Извините за предоставление только подхода, а не решения, но, возможно, я надеюсь, что мои мысли помогут вам (немного).
Эта и другая информация доступна на Twigs "для" Docu!
Ответ 5
Взял ответ на грипп и немного изменил его:
{# 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) }}
Ответ 6
Ответы здесь приводят меня к моему решению.
У меня есть объект категории с самосвязанной ассоциацией 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>