Twigでツリーをレンダリングする方法


89

深さが不定の樹木(子供達の子供達など)をレンダリングしたい。配列を再帰的にループする必要があります。Twigでこれを行うにはどうすればよいですか?

回答:


117

domi27のアイデア遊んだて、これを思いつきました。私はツリーとしてネストされた配列を作成しました。['link'] ['sublinks']がnullまたはそれ以上の別の配列です。

テンプレート

再帰するサブテンプレートファイル:

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

次に、メインテンプレートでこれを呼び出します(冗長な「with」のようなものです)。

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

コメント付きのプロジェクトで1つの問題がありました。サブコメント(サブリンク)もメインコレクション(リンク)に含まれていました。インクルードする前に、コメントに「親」エントリがあるかどうかを確認する必要がありました。
Jevgeni Smirnov 2013

4
使用{{_self.menu_links}}悪い習慣です!ここでメモをお読みください:マクロ使用 するテンプレートでマクロを定義する場合、マクロをインポートする代わりに、_self.input()を介して直接呼び出したくなるかもしれません。機能しているように見えても、これは現在の実装の副作用にすぎず、Twig 2.xでは機能しなくなります。マクローゼを再びローカルでローカルにインポートする必要がありますmenu_links
dr.scre

35

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

とおり小枝2.11、あなたは省略することができます{% import _self as macros %}インラインマクロが下に自動的にインポートされているように、_self名前空間(参照小枝発表:自動マクロインポート):

{# {% 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以降を実行している場合、Alain Tiembloによるこの問題の素晴らしい新しい解決策(2016年5月現在)があります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

まず、これは簡単な方法で解決できると思いましたが、それは簡単ではありません。

Twigサブテンプレートを含める場合と含めない場合は、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>

そのため、Twig forループ内で使用できる特別なTwigループ変数を使用できます。しかし、このループ変数のスコープについてはわかりません。

この情報およびその他の情報は、Twigsの「for」Docuで入手できます。


0

インフルエンザの答えを取り、それを少し修正しました:

{# 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) }}

-1

ここでの答えは私を私の解決策に導きます。

自己参照の多対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>

複数レベルのカテゴリ階層がある場合はどうなりますか?
16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.