🗂

【WordPress】記事が属する子タームを親タームを基準とした順番で表示する

2022/12/27に公開

概要

久しぶりにWordpressの案件で、方法が分からず調べたのでメモしておく。
通常、記事を投稿した際に、属してるターム(カテゴリーなど)は一つだけしか出力しなかったりする。
今回やりたいことは、カスタム投稿タイプで記事を投稿した時に以下の事をやりたいと思ってます。

  • 属しているタームを全て表示したい。
  • 記事が複数の子タームを持つとき、ターム一覧を親タームを基準として好きな順番(例:地域・ジャンル・開始年の順番)で表示させたい。

これを親のタームを基準となると手間がかかります。

タームの構成

実際の構成は以下のようになります。(適当です)
地域・ジャンル・開始年という親のタームがあり、実際に投稿する際は親のタームにはチェックを入れません。

今回はカスタム投稿タイプなので以下のように設定しているテイです。
カスタム投稿タイプ:sample
カスタムタクソノミー:sample_terms

-地域(親ターム)
--東京
--神奈川
--埼玉

-ジャンル(親ターム)
--飲食
--小売
--その他

-開始年(親ターム)
--2001年
--2006年
--2008年

通常、タームを設定して普通に出力しると以下のようにタームがバラバラで出力されることがあります。これだと統一感もないですよね。

実施にWEBサイトで表示する際に記事一覧や新着情報で表示させる場合に下記のようにしたい。
左から地域・ジャンル・開始年という順番でそれぞれターム事に色が違います。
この方が分かりやすいですよね。

実装方法

実際に実装するにあたって、親タームを基準とするには数字が必要となります。
親のタームID順にしてもいいのですが、後で「開始年から左から~~」とか言われるとタームを作りなおしたりと後々めんどくさいので、変更できるようにカスタムフィールドを使います。

カスタムフィールドの設定

カスタムフィールドの説明はしませんが、下記のようにフィールド名を「sort-order」として登録します。

「このフィールドグループを表示する条件」として「タクソノミー」を選択しておけば、以下のようにタームを作成する画面に作成したカスタムフィールドが表示されるはずです。

実際にタームを作成する場合は、タームの構成の親のタームを作成する際に「カテゴリー表示順」の部分に数値を入力していく。
例えば、左から「地域/ジャンル/開始年」と表示させたいのであれば「0/5/10」と5きざみでもいいし「0/1/2」と各親タームに数値を設定してもよい。

ソースコード全体

実装したのは、「archive-〇〇.php」「taxonomy-〇〇_terms.php」「single-〇〇.php」です。
*下記のコードはhtmlに出力する部分は端折ってます。


if (have_posts()) : while (have_posts()) : the_post(); ?>
   //記事が所属しているタームを取得
   $article_terms = get_the_terms($post->ID, 'sample_terms');
   if (!empty($article_terms) && !is_wp_error($article_terms)) {
       
      //比較関数
      usort($article_terms, function($a, $b) {
          //親のタームIDから
          $term_a="sample_terms_".$a->parent;
          $term_b="sample_terms_".$b->parent;
	  
	  //カスタムフィールドから数字を取得する
          $nums_a=get_field("sort-order",$term_a);
          $nums_b=get_field("sort-order",$term_b);
                                
          if ( $a->parent == $b->parent ) {
               return 0;
           }
           return ( $nums_a > $nums_b ) ? 1 : -1;
       });
    }
 
 endwhile; wp_reset_postdata(); endif;

まず、Wordpressの通常のループ内で各記事が属しているタームを取得するために、get_the_termsで取得します。すると配列でデータが返ってきます。

次に並び替えをさせたいのでusort()の比較関数の使います。
引数として、$a, $bから子タームの情報がとれるので、そこから$a->parent``$b->parentとすることで親のタームIDが取得できる。
親のタームIDを利用してカスタムフィールドに設定したsort-orderの値を取得したいが、少しルールがある。通常、各記事のカスタムフィールドの値は、下記のように取得できる。

get_field('カスタムフィールド名', $post->ID)

ただターム(カテゴリー)に紐づけたカスタムフィールドの取得の場合、$post->IDではなく「カスタム分類(タクソノミー)名_タームID」にする必要がある。その為、下記にように「sample_terms_(アンダーバー)」と親タームIDを連結している。

$term_a="sample_terms_".$a->parent;
$term_b="sample_terms_".$b->parent;

あとはget_filedでカスタムフィールドの値(数値)が取得できるので数値を比較して並び替えを行っている。並び替えしたら後は、通常のループ内でforeachで出力すればいい。

<ul>
    <?php 
     foreach($article_terms as $index=>$term): 
     ?>
     <li><?php echo $term->name; ?></li>
    <?php endforeach; ?>
 </ul>

usort()による比較関数に関してはネットでいくらでも検索でてくるので説明は省きます。
https://www.php.net/manual/ja/function.usort.php

親のタームIDで出力したい場合

今回は、カスタムフィールドの値で並び替えをしたが、親のタームIDの数値だけでも並び替えができる。ただし、親のタームを作成した段階で自動的にIDが割り振られてしまい、今回はそれで困ったのでカスタムフィールドを利用した。
親のタームIDで並び替える場合はカスタムフィールドを使わないだけです。

//比較関数
usort($article_terms, function($a, $b) {
if ( $a->parent == $b->parent ) {
     return 0;
}
 return ( $nums_a > $nums_b ) ? 1 : -1;
});

並び替えはしない場合

一応、並び替えとか必要ない!っていう場合はusort()による比較関数も必要ないのでforeach$term->parentで親のタームIDから取得すればいい。

foreach ($article_terms as $term){
    $term_idsp="sample_terms_".$term->parent;
    $nums=get_field("sort-order",$term_idsp);
 }

まとめ

今回、参考にさせていただいた記事です。
https://www.tam-tam.co.jp/tipsnote/cms/post6651.html
https://teratail.com/questions/122063
https://100webdesign.jp/services/wordpress/wp_result/wp_result-391/

Discussion