Как сделать дерево в Twig - PullRequest
       24

Как сделать дерево в Twig

88 голосов
/ 30 ноября 2011

Я хотел бы сделать дерево с неопределенной глубиной (дети детей, дети и т. Д.).Мне нужно рекурсивно перебирать массив;как я могу сделать это в Twig?

Ответы [ 6 ]

105 голосов
/ 12 декабря 2011

Спасибо, 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>

Надеюсь, это поможет:)

32 голосов
/ 17 апреля 2014

Если вы хотите использовать Макрос в том же шаблоне , вы должны использовать что-то подобное, чтобы остаться совместимым с 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 к документации ветки о макросах , чтобы теперь использовать _self, но импортировать локально.


Редактировать (2019-07-01):

Начиная с 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 голосов
/ 14 мая 2016

Если вы используете PHP 5.4 или выше, Alain Tiemblo предлагает прекрасное новое решение (по состоянию на май 2016 года): https://github.com/ninsuo/jordan-tree.

Это тег "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 голос
/ 01 декабря 2011

Сначала я подумал, что это может быть решено просто - но это не так просто.

Вам нужно создать логику, возможно, с помощью метода класса php, когда включать подшаблон ветки, а когда нет..

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

0 голосов
/ 19 октября 2017

Взял ответ гриппа и немного его изменил:

{# 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) }}
0 голосов
/ 08 июля 2015

Ответы здесь приводят меня к моему решению.

У меня есть объект категории с самосвязанной ассоциацией ManyToOne (родитель для детей).

/**
 * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
 */
private $parent;

/**
 * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
 */
private $children;

В моем шаблоне ветки я выполняю рендерингдерево выглядит так:

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