Chciałbym wyrenderować drzewo o nieokreślonej głębokości (dzieci dzieci itp.). Muszę cyklicznie przechodzić przez tablicę; jak mogę to zrobić w Twig?
Odpowiedzi:
I bawił się pomysłem domi27 męska i wpadł na to. Zrobiłem zagnieżdżoną tablicę jako moje drzewo, ['link'] ['podrzędne'] ma wartość null lub inną tablicę, która zawiera więcej takich samych.
Szablony
Plik pod-szablonu do ponownego wykorzystania:
<!--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 %}
Następnie w głównym szablonie nazwij to (rodzaj zbędnych rzeczy tam „z”):
<ul class="main-menu">
{% include "includes/menu-links.html" with {'links':links} only %}
</ul>
Makra
Podobny efekt można osiągnąć za pomocą makr:
<!--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 %}
W głównym szablonie zrób to:
{% import "macros/menu-macros.html" as macros %}
<ul class="main-menu">
{{ macros.menu_links(links) }}
</ul>
{{_self.menu_links}}
to zła praktyka ! Przeczytaj notatkę tutaj: makro Gdy definiujesz makro w szablonie, w którym zamierzasz go użyć, możesz ulec pokusie wywołania makra bezpośrednio przez _self.input () zamiast importowania go; nawet jeśli wydaje się działać, jest to tylko efekt uboczny obecnej implementacji i nie będzie już działać w Twig 2.x. Powinieneś ponownie zaimportować makra lokalnie insitemenu_links
Jeśli chcesz użyć makra w tym samym szablonie , powinieneś użyć czegoś takiego, aby pozostać kompatybilnym z 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>
To rozszerza random-coder
odpowiedź i włącza dr.scre
wskazówkę do dokumentacji Twig na temat makr, które mają być teraz używane _self
, ale importowane lokalnie.
Począwszy od Twig 2.11 , możesz pominąć {% import _self as macros %}
, ponieważ wbudowane makra są importowane automatycznie w _self
przestrzeni nazw (zobacz ogłoszenie Twig: Automatyczny import makr ):
{# {% import _self as macros %} - Can be removed #}
<ul class="main-menu">
{{ _self.menu_links(links) }} {# Use _self for inlined macros #}
</ul>
Jeśli korzystasz z PHP 5.4 lub nowszego, istnieje wspaniałe nowe rozwiązanie (stan na maj 2016 r.) Autorstwa Alaina Tiemblo: https://github.com/ninsuo/jordan-tree .
Jest to tag „drzewo”, który służy właśnie do tego celu. Znaczniki wyglądałyby następująco:
{% 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
. W moim przypadku kod musi wiedzieć, czy będzie więcej dzieci i przekazuje liczbę poziomów do makra, aby mogło wykonać plik <div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">
. Obliczenie tego wymagałoby powtórnego powtórzenia bieżącego poziomu, aby uchwycić, czy są jakieś dzieci.
Najpierw pomyślałem, że można to rozwiązać w prosty sposób, ale nie jest to takie łatwe.
Musisz stworzyć logikę, być może za pomocą metody klasy PHP, kiedy dołączyć podszablon Twig, a kiedy nie.
<!-- 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>
Możesz więc użyć specjalnej zmiennej pętli Twig , która jest dostępna wewnątrz pętli Twig for . Ale nie jestem pewien co do zakresu tej zmiennej pętli .
Te i inne informacje są dostępne na Twigs „for” Docu !
Wziąłem odpowiedź grypy i trochę ją zmodyfikowałem:
{# 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) }}
Odpowiedzi tutaj prowadzą mnie do mojego rozwiązania.
Mam jednostkę kategorii z odwołującym się do siebie skojarzeniem wiele do jednego (rodzic do dzieci).
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
W moim szablonie Twig renderuję widok drzewa w następujący sposób:
<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) }}
.