Saya ingin membuat pohon dengan kedalaman yang tidak dapat ditentukan (anak dari anak dari anak kecil, dll.). Saya perlu mengulang melalui array secara rekursif; bagaimana saya bisa melakukan ini di Twig?
Jawaban:
Saya bermain-main dengan ide domi27 dan muncul dengan ini. Saya membuat array bersarang sebagai pohon saya, ['link'] ['sublinks'] adalah null atau array lain yang lebih sama.
Template
File sub-template untuk digunakan kembali dengan:
<!--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 %}
Kemudian di template utama, panggil ini (semacam 'dengan' barang di sana):
<ul class="main-menu">
{% include "includes/menu-links.html" with {'links':links} only %}
</ul>
Makro
Efek serupa dapat dicapai dengan makro:
<!--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 %}
Di template utama, lakukan ini:
{% import "macros/menu-macros.html" as macros %}
<ul class="main-menu">
{{ macros.menu_links(links) }}
</ul>
{{_self.menu_links}}
adalah praktik yang buruk ! Baca catatan di sini: makro Saat Anda menentukan makro di templat tempat Anda akan menggunakannya, Anda mungkin tergoda untuk memanggil makro secara langsung melalui _self.input () daripada mengimpornya; meskipun tampaknya berhasil, ini hanyalah efek samping dari implementasi saat ini dan tidak akan berfungsi lagi di Twig 2.x. Anda harus mengimpor macroses secara lokal sekali lagi di insitemenu_links
Jika Anda ingin menggunakan makro di template yang sama , Anda harus menggunakan sesuatu seperti ini agar tetap kompatibel dengan 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>
Ini memperluas random-coder
jawaban dan memasukkan dr.scre
petunjuk ke dokumentasi Twig tentang makro yang sekarang digunakan _self
, tetapi mengimpor secara lokal.
Mulai Twig 2.11 , Anda dapat menghilangkan {% import _self as macros %}
, karena makro sebaris diimpor secara otomatis di bawah _self
namespace (lihat Pengumuman Twig: Impor makro otomatis ):
{# {% import _self as macros %} - Can be removed #}
<ul class="main-menu">
{{ _self.menu_links(links) }} {# Use _self for inlined macros #}
</ul>
Jika Anda menjalankan PHP 5.4 atau lebih tinggi, ada solusi baru yang luar biasa (per Mei 2016) untuk masalah ini oleh Alain Tiemblo: https://github.com/ninsuo/jordan-tree .
Ini adalah tag "pohon" yang memiliki tujuan persis seperti ini. Markup akan terlihat seperti ini:
{% 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
. Dalam kasus saya, kode perlu mengetahui apakah akan ada lebih banyak anak dan melewati jumlah level ke makro sehingga dapat melakukan a <div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">
. Menghitung ini akan membutuhkan pengulangan level saat ini untuk kedua kalinya hanya untuk menangkap apakah ada anak.
Pertama saya pikir ini dapat diselesaikan dengan cara yang mudah, tetapi tidak semudah itu.
Anda perlu membuat logika, mungkin dengan metode kelas PHP, kapan harus menyertakan subtemplate Twig dan kapan tidak.
<!-- 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>
Jadi Anda bisa menggunakan variabel loop Twig khusus , yang tersedia di dalam Twig for loop . Tapi saya tidak yakin tentang ruang lingkup variabel loop ini .
Ini dan informasi lainnya tersedia di Twigs "untuk" Docu !
Mengambil jawaban flu dan mengubahnya sedikit:
{# 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) }}
Jawaban di sini menuntun saya ke solusi saya.
Saya memiliki entitas kategori dengan asosiasi banyak ke satu yang merujuk sendiri (induk ke anak).
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
Dalam template Twig saya, saya membuat tampilan pohon seperti ini:
<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) }}
.