Craft CMS のストラクチャーで親子関係のデータを取得する

これは Craft CMS Advent Calendar 2017 16日目の記事です。
今回は、ストラクチャータイプのセクションを例に親子関係にあたるエントリを取得する方法についてまとめてみます。

セクションの作成

はじめにストラクチャータイプのセクションを作成し、エントリを登録しておきましょう。

階層構造を持ったエントリ一覧のサンプル

ここでは、サンプルとして 汎用ページ(ハンドル:page) というセクションを作成し、3階層のエントリを用意しました。

子エントリを取得する

ローカルナビゲーションの出力といった場合に使える、子エントリの取得サンプルです。

{# 「企業情報」エントリの詳細ページ以外を想定し、明示的に基準エントリを取得 #}
{% set baseEntry = craft.entries.section('page').title('企業情報').first() %}

{# 基準エントリの子孫エントリをすべて取得 #}
{% set childEntries = craft.entries.section('page').descendantOf(baseEntry) %}

<ul>
  {# 子孫エントリをループ処理 #}
  {% for childEntry in childEntries %}
    <li><a href="{{ childEntry.url }}">{{ childEntry.title }}</a></li>
  {% endfor %}
</ul>

ポイントは .descendantOf(baseEntry) の部分で、これにより baseEntry の子孫エントリを取得します。
複数の階層が存在する場合、 .descendantDist(1) とすることで子エントリのみに制限することも可能です。

{# 「採用情報」エントリの詳細ページ以外を想定し、明示的に基準エントリを取得 #}
{% set baseEntry = craft.entries.section('page').title('採用情報').first() %}

{# 基準エントリの子エントリのみ、すべて取得 #}
{% set childEntries = craft.entries.section('page').descendantOf(baseEntry).descendantDist(1) %}

<ul>
  {# 子エントリをループ処理 #}
  {% for childEntry in childEntries %}
    <li><a href="{{ childEntry.url }}">{{ childEntry.title }}</a></li>
  {% endfor %}
</ul>

このサンプルでは、先のキャプチャ画像の 募集要項 と同階層のエントリだけが出力されます。

親エントリを取得する

次に、親エントリを取得してみましょう。パンくずリストを出力する際などに有効です。

{# 「新卒採用」エントリの詳細ページ以外を想定し、明示的に基準エントリを取得 #}
{% set baseEntry = craft.entries.section('page').title('新卒採用').first() %}

{# 基準エントリの親エントリをすべて取得 #}
{% set parentEntries = craft.entries.section('page').ancestorOf(baseEntry) %}

<ul>
  <li><a href="{{ siteUrl }}">HOME</a></li>

  {# 親エントリをループ処理 #}
  {% for parentEntry in parentEntries %}
    <li><a href="{{ parentEntry.url }}">{{ parentEntry.title }}</a></li>
  {% endfor %}

  {# 自身のエントリを出力 #}
  <li><span>{{ baseEntry.title }}</span></li>
</ul>

ここでもポイントは .ancestorOf(baseEntry) の部分で、これにより baseEntry の親エントリを取得します。
子エントリの場合と同様に .ancestorDist(1) でレベルを制限することが可能です。

{# 「新卒採用」エントリの詳細ページ以外を想定し、明示的に基準エントリを取得 #}
{% set baseEntry = craft.entries.section('page').title('新卒採用').first() %}

{# 基準エントリのひとつ上の階層にあたる親エントリのみを取得 #}
{% set parentEntries = craft.entries.section('page').ancestorOf(baseEntry).ancestorDist(1) %}

<ul>
  {# 親エントリをループ処理 #}
  {% for parentEntry in parentEntries %}
    <li><a href="{{ parentEntry.url }}">{{ parentEntry.title }}</a></li>
  {% endfor %}
</ul>

このサンプルでは、募集要項 のリンクテキストが出力されます。

まとめ

ストラクチャータイプのセクションであれば、親子関係にあたるエントリを比較的簡単に取得できて便利ですね。

なお、 craft.entries.section('page') にあたる箇所を craft.categories.group('カテゴリーグループのハンドル') とするだけでカテゴリーも同様に処理することができます。