LOADING

BLOG

HOME > BLOG > 技術 > PHP > WordPress > タクソノミーの親子関係の階層を維持したタームリストを全件出力する方法

タクソノミーの親子関係の階層を維持したタームリストを全件出力する方法

PHPWordPress技術

タクソノミーのターム一覧を出力する際には、get_terms()を使ってリストを取得ことが多いかと思います。
しかし、親子関係を維持した階層構造で取得するにはget_terms()だけではできません。

今回はブログ等によくあるカテゴリー(ターム)一覧を想定して、出力する方法を紹介します。

再帰的に呼び出して出力する関数

さっそく関数の紹介です。
関数をfunctions.php等に記述して、出力するテンプレートファイルから呼び出します。

  /**
   * 指定したタームの子どもを再帰的に取得してリスト出力
   *
   * @param string $taxonomy_slug
   * @param \WP_Term|null $parent_term
   * @return void
   */
  function taxonomy_tree($taxonomy_slug, $parent_term = null) {
    $parent_term_id = 0;
    if ($parent_term !== null) {
      $parent_term_id = $parent_term->term_id;
    }

    $terms = get_terms($taxonomy_slug, array('hide_empty' => false, 'parent' => $parent_term_id));

    if (!empty($terms)) {
      echo '<ul>';
      foreach ($terms as $term) {
        echo '<li>';
          echo '<a href="' . get_term_link($term) . '">' . $term->name . '(' . $term->count . ')</a>';
          taxonomy_tree($taxonomy_slug, $term);
        echo '</li>';
      }
      echo '</ul>';
    }
  }

使い方

関数の使い方としては2パターン想定しています。

  • タームを全件出力する方法
  • 親タームを指定して出力する方法

タームを全件出力する方法

全件を出力する場合は、第1引数にタクソノミーのスラッグを指定します。
そうすると、最上位の親から順に階層的に全タームが出力されます。

// タクソノミーのスラッグを渡す
taxonomy_tree('taxonomy_slug');

親タームを指定して出力する方法

親タームを指定する場合は、第1引数にタクソノミーのスラッグ。
第2引数に親タームのタームオブジェクト(WP_Term)を指定します。

タームオブジェクトの取得は、get_terms()で取得した配列から取り出したり、get_term()で取得したオブジェクトを渡します。

// タクソノミーのスラッグと親タームオブジェクト(WP_Term)を渡す
taxonomy_tree('taxonomy_slug', $parent_term);

出力結果

出力結果の例としては、以下のようなリストになります。
<ul></ul>のリストが出力され、子タームを持つ場合はさらに内部に<ul></ul>が出力されます。
それぞれ各タームのアーカイブページへリンクしているのと、ターム名の後ろにカッコで記事件数が出力されます。

<ul>
  <li>
    <a href="ターム記事一覧">ターム1(件数)</a>
    <ul>
      <li><a href="ターム記事一覧">ターム1-1(記事件数)</a></li>
      <li><a href="ターム記事一覧">ターム1-2(記事件数)</a>
        <ul>
          <li><a href="ターム記事一覧">ターム1-2-1(記事件数)</a></li>
          <li><a href="ターム記事一覧">ターム1-2-2(記事件数)</a></li>
        </ul>
      </li>
      <li><a href="ターム記事一覧">ターム1-3(記事件数)</a></li>
    </ul>
  </li>
  <li>
    <a href="ターム記事一覧">ターム2(記事件数)</a>
    <ul>
      <li><a href="ターム記事一覧">ターム2-1(記事件数)</a></li>
      <li><a href="ターム記事一覧">ターム2-2(記事件数)</a></li>
    </ul>
  </li>
</ul>

関数の解説

今回の関数はタームの親子関係を維持したまま、全件出力することを目的としています。

よく他サイトで解説されている方法では、get_terms()で取得した配列をforeach()で2重ループしたりするのを見かけます。しかし、その方法では2階層目までしか取得するとこができません。
3階層目も出力したい場合は3重ループに変更する必要がありますが、タームの階層が変わるたびにコードを改変するのであれば、ただただ煩雑ですし、汎用性がありません。

そのため今回は再帰的に関数を呼び出すことで、階層が増えててもコードを変えることなく出力できるようにしています。

再帰的とは

自分自身を呼び出す関数を再帰的である、またそのような関数を再帰関数と呼びます。

「指定した親タームの子タームを出力する」関数が、さらに自らの関数を呼ぶことで、子どもが見つかり限り自身を呼び続けます。
そのため、全階層分のタームが出力されます。

出力されるHTMLを変更するには

出力されるHTMLを変更するには、関数内の以下の部分を変更してください。
classを付けたり、<ul></ul>タグから変更したり自由な構成に変更が可能です。

echo '<ul>';
foreach ($terms as $term) {
  echo '<li>';
    echo '<a href="' . get_term_link($term) . '">' . $term->name . '(' . $term->count . ')</a>';
    taxonomy_tree($taxonomy_slug, $term);
  echo '</li>';
}
echo '</ul>';

記事件数が0件のタームを出力しないようにするには

記事件数が空のタームが出力されないようにするには、以下の'hide_empty' => false'hide_empty' => trueへ変更します。

$terms = get_terms($taxonomy_slug, array('hide_empty' => false, 'parent' => $parent_term_id));