Tôi muốn kết xuất một cái cây với độ sâu không xác định (trẻ em của trẻ em, v.v.). Tôi cần lặp qua mảng một cách đệ quy; làm thế nào tôi có thể làm điều này trong Twig?
Câu trả lời:
Tôi đã thử với ý tưởng của domi27 và nghĩ ra điều này. Tôi đã tạo một mảng lồng nhau dưới dạng cây của tôi, ['link'] ['sublinks'] là null hoặc một mảng khác giống nhau hơn.
Mẫu
Tệp mẫu phụ để đệ quy:
<!--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 %}
Sau đó, trong mẫu chính, hãy gọi điều này (loại thừa 'với' thứ ở đó):
<ul class="main-menu">
{% include "includes/menu-links.html" with {'links':links} only %}
</ul>
Macro
Hiệu ứng tương tự có thể đạt được với macro:
<!--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 %}
Trong mẫu chính, hãy làm như sau:
{% import "macros/menu-macros.html" as macros %}
<ul class="main-menu">
{{ macros.menu_links(links) }}
</ul>
{{_self.menu_links}}
là một thực hành xấu ! Đọc ghi chú ở đây: macro Khi bạn xác định một macro trong mẫu mà bạn sẽ sử dụng nó, bạn có thể muốn gọi macro trực tiếp qua _self.input () thay vì nhập nó; ngay cả khi có vẻ hoạt động, đây chỉ là một tác dụng phụ của việc triển khai hiện tại và nó sẽ không hoạt động nữa trong Twig 2.x. Bạn nên nhập macro cục bộ một lần nữa trong trangmenu_links
Nếu bạn muốn sử dụng macro trong cùng một mẫu , bạn nên sử dụng một cái gì đó như thế này để duy trì tương thích với 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>
Điều này mở rộng random-coder
câu trả lời của và kết hợp dr.scre
gợi ý với tài liệu Twig về macro để sử dụng bây giờ _self
, nhưng nhập cục bộ.
Kể từ Twig 2.11 , bạn có thể bỏ qua {% import _self as macros %}
, vì macro nội tuyến được nhập tự động trong _self
không gian tên (xem thông báo Twig: Nhập macro tự động ):
{# {% import _self as macros %} - Can be removed #}
<ul class="main-menu">
{{ _self.menu_links(links) }} {# Use _self for inlined macros #}
</ul>
Nếu bạn đang chạy PHP 5.4 trở lên, có một giải pháp mới tuyệt vời (kể từ tháng 5 năm 2016) cho vấn đề này của Alain Tiemblo: https://github.com/ninsuo/jordan-tree .
Đó là một thẻ "cây" phục vụ mục đích chính xác này. Đánh dấu sẽ giống như sau:
{% 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
. Trong trường hợp của tôi, mã cần biết liệu sẽ có nhiều con hơn hay không và nó chuyển số cấp đến macro để nó có thể thực hiện a <div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">
. Việc tính toán điều này sẽ yêu cầu lặp lại mức hiện tại lần thứ hai chỉ để nắm bắt xem có bất kỳ con nào hay không.
Đầu tiên, tôi nghĩ điều này có thể được giải quyết một cách dễ dàng, nhưng nó không dễ dàng như vậy.
Bạn cần tạo logic, có thể với một phương thức lớp PHP, khi nào thì đưa vào phương thức con Twig và khi nào thì không.
<!-- 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>
Vì vậy, bạn có thể sử dụng biến vòng lặp Twig đặc biệt , có sẵn bên trong vòng lặp Twig for . Nhưng tôi không chắc về phạm vi của biến vòng lặp này .
Thông tin này và các thông tin khác có trên Twigs "for" Docu !
Nhận câu trả lời của bệnh cúm và sửa đổi nó một chút:
{# 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) }}
Các câu trả lời ở đây dẫn tôi đến giải pháp của tôi.
Tôi có một thực thể danh mục với liên kết nhiều-một tự tham chiếu (cha mẹ với con cái).
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
Trong mẫu Twig của tôi, tôi đang hiển thị chế độ xem dạng cây như sau:
<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) }}
.