วิธีการสร้างต้นไม้ใน Twig


90

ฉันต้องการสร้างต้นไม้ที่มีความลึกไม่แน่นอน (ลูกของลูก ๆ ฯลฯ ) ฉันต้องวนซ้ำอาร์เรย์ซ้ำ ฉันจะทำสิ่งนี้ใน Twig ได้อย่างไร

คำตอบ:


117

ฉันเล่นกับความคิดของ 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 %}

จากนั้นในเทมเพลตหลักให้เรียกสิ่งนี้ (ประเภทซ้ำซ้อน 'กับ' ที่นั่น):

<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>

9
ดีมากขอบคุณ! หากคุณต้องการใช้มาโครในเทมเพลตเดียวกันคุณสามารถ{{ _self.menu_links(links) }}ใช้ได้
ไข้หวัด

ขอบคุณความคิดนี้ทำให้สมองของฉันเจ็บปวด แต่คำตอบของคุณก็สมเหตุสมผลดี
azzy81

ฉันมีปัญหาหนึ่งเกี่ยวกับโครงการของฉันพร้อมความคิดเห็น ความคิดเห็นย่อย (ลิงก์ย่อย) รวมอยู่ในคอลเลกชันหลักด้วย (ลิงก์) ดังนั้นก่อนรวมฉันต้องตรวจสอบว่าความคิดเห็นมีรายการ "ผู้ปกครอง" หรือไม่
Jevgeni Smirnov

4
การใช้{{_self.menu_links}}เป็นการปฏิบัติที่ไม่ดี ! อ่านหมายเหตุที่นี่: มาโคร เมื่อคุณกำหนดมาโครในเทมเพลตที่คุณจะใช้คุณอาจถูกล่อลวงให้เรียกใช้มาโครโดยตรงผ่าน _self.input () แทนที่จะนำเข้า แม้ว่าดูเหมือนจะใช้งานได้ แต่นี่เป็นเพียงผลข้างเคียงของการใช้งานปัจจุบันและจะไม่ทำงานอีกต่อไปใน Twig 2.x คุณควรนำเข้ามาโครภายในเครื่องอีกครั้งmenu_links
dr.scre

37

ทวิก 2.0 - 2.11

หากคุณต้องการใช้มาโครในเทมเพลตเดียวกันคุณควรใช้สิ่งนี้เพื่อให้เข้ากันได้กับ 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แต่นำเข้าภายในเครื่อง

ทวิก> = 2.11

ใน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>

2

หากคุณกำลังใช้ PHP 5.4 หรือสูงกว่ามีวิธีใหม่ยอดเยี่ยม ( ณ พฤษภาคม 2016) ในการแก้ไขปัญหานี้โดย Alain Tiemblo: 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 %}

1
subtreeคุณไม่สามารถผ่านตัวแปรเพิ่มเติมเพื่อ ในกรณีของฉันรหัสต้องการทราบว่าจะมีลูกเพิ่มขึ้นหรือไม่และส่งผ่านจำนวนระดับไปยังมาโครจึงจะสามารถทำไฟล์<div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">. การคำนวณสิ่งนี้จะต้องทำซ้ำระดับปัจจุบันเป็นครั้งที่สองเพื่อจับภาพว่ามีลูกหรือไม่
chx

1

ก่อนอื่นฉันคิดว่าสิ่งนี้อาจแก้ไขได้อย่างตรงไปตรงมา แต่มันไม่ง่ายอย่างนั้น

คุณต้องสร้างลอจิกอาจจะใช้เมธอดคลาส 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>

เพื่อให้คุณสามารถใช้พิเศษทวิตัวแปร loopซึ่งมีอยู่ภายในทวิห่วง แต่ฉันไม่แน่ใจเกี่ยวกับขอบเขตของตัวแปรลูปนี้

ข้อมูลนี้และข้อมูลอื่น ๆ มีอยู่ในTwigs "สำหรับ" Docu !



-1

คำตอบที่นี่นำไปสู่การแก้ปัญหาของฉัน

ฉันมีเอนทิตีประเภทที่มีการเชื่อมโยงแบบหลายต่อหนึ่งที่อ้างอิงตัวเอง (พ่อแม่ถึงลูก)

/**
 * @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>

จะเป็นอย่างไรหากคุณมีลำดับชั้นหมวดหมู่มากกว่าหนึ่งระดับ
pmoubed
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.