カスタムタクソノミーのターム一覧リストを表示するには、get_terms()
を使うことが多いかと思います。
この時、wp_list_categories()
で出力するリストのように、親子階層に合わせてリストタグを入れ子構造で出力するには、一手間加える必要があります。
例えば、親タームの<li>
タグの中で、その子タームのリストを.children
クラス付きの別の<ul>
タグとして出力するなどです。
こんな感じのリストを出力したいケース。
<ul>
<li>
親タームA
<ul class="children">
<li>子タームA-1</li>
<li>子タームA-2</li>
<li>子タームA-3</li>
</li>
<li>
親タームB
<ul class="children">
<li>子タームB-1</li>
<li>子タームB-2</li>
</li>
</ul>
今回は、タクソノミーのターム一覧リストを、上記のような構造で出力する方法を紹介していきます。
方法1:ループを2重で回す
まず、第1階層(一番親となるターム)のデータを取得してループを回し、それぞれの子タームをさらに取得してループさせるという手法です。
<?php
$my_tax = 'my-taxonomy'; //取得したいタクソノミー名
$parent_terms = get_terms( $my_tax, array('hide_empty' => false, 'parent' => 0) ); //第一階層のタームだけ取得
if ( !empty( $parent_terms ) ) :
echo '<ul>';
//第1ループ
foreach ( $parent_terms as $pt ) :
$pt_id = $pt->term_id;
$pt_name = $pt->name;
$pt_url = get_term_link($pt);
?>
<li>
<a href="<?php echo $pt_url; ?>"><?php echo $pt_name; ?></a>
<?php
$child_terms = get_terms( $my_tax, array('hide_empty' => false, 'parent' => $pt_id) );
if ( !empty( $child_terms ) ) :
echo '<ul class="child">';
//第2ループ
foreach ( $child_terms as $ct ) :
$ct_id = $ct->term_id;
$ct_name = $ct->name;
$ct_url = get_term_link($ct);
?>
<li>
<a href="<?php echo $ct_url; ?>"><?php echo $ct_name; ?></a>
</li>
<?php
endforeach; //End : 第2ループ
echo '</ul>';
endif;
?>
</li>
<?php
endforeach; //End : 第1ループ
echo '</ul>';
endif;
?>
第1階層のタームを取得するために、まずはget_terms()
でのデータ取得時に'parent' => 0
を指定しています。
それらのデータをforeach
でループさせ、さらにget_terms()
で'parent' => $pt_id
としてその子タームのリストを取得しています。
3階層までの入れ子構造で出力させたい場合は、さらにループさせる必要があります。
方法2:walk_category_tree()を使う
walk_category_tree()
という関数を使えば、非常に簡単なコードで済みます。
$my_tax = 'my-taxonomy';
$terms = get_terms( $my_tax, array('hide_empty' => false) );
echo walk_category_tree( $terms, 0 , array(
'style' => 'list', //wp_list_categories() のようなリスト構造になる
));
このwalk_category_tree()
を使った場合に出力されるHTMLでは、子タームリストの ulタグ に付与されるクラス名はchildren
です。
リンクにtitle属性を出力しないように'use_desc_for_title' => false
というパラメータを指定している記事が多かったんですが、これはなくても大丈夫でした。(wordpress5.2.2で検証)
また、この方法だと全階層が出力されるっぽいです。
試しに'depth'
パラメータは指定してみたのですが、効きませんでした。(他に方法はあるかもです。)
第2階層までしか表示させたくないと言う場合は、方法①を使うか、CSSで非表示にするといいでしょう。