深さが不定の樹木(子供達の子供達など)をレンダリングしたい。配列を再帰的にループする必要があります。Twigでこれを行うにはどうすればよいですか?
回答:
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>
同じテンプレートでマクロを使用する場合は、次のようなものを使用して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、あなたは省略することができます{% 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>
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 %}
subtree
。私の場合、コードはさらに子が存在するかどうかを知る必要があり、レベル数をマクロに渡して<div class="{{ classes[current_level].wrapper }} {% if levels > current_level %}accordion-wrapper{% endif %}">
。これを計算するには、子があるかどうかをキャプチャするためだけに、現在のレベルをもう一度繰り返す必要があります。
まず、これは簡単な方法で解決できると思いましたが、それは簡単ではありません。
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で入手できます。
インフルエンザの答えを取り、それを少し修正しました:
{# 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の関連付け(親から子)を持つカテゴリエンティティがあります。
/**
* @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>
{{ _self.menu_links(links) }}
。