Я хотів би зробити дерево з невизначеною глибиною (діти дітей, дітей тощо). Мені потрібно прокрутити масив рекурсивно; як я можу це зробити в Twig?
Відповіді:
Я погрався з ідеєю 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>
{{_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 або новішої версії, є чудове нове рішення (станом на травень 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 %}
subtree
. У моєму випадку код повинен знати, чи буде більше дітей, і він передає кількість рівнів макросу, щоб він міг зробити a <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 . Але я не впевнений в області дії цієї змінної циклу .
Ця та інша інформація доступна на Twigs "для" 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) }}
.