WP_Queryによる親子ターム別投稿一覧の表示

あるカスタム投稿で親子タームを設定した場合、その表示の指定は比較的複雑になります。今回は特定タクソノミーの親子タームごとに投稿一覧を表示させる方法について触れます。

目的の表示内容

投稿表示の条件

設定条件は下記のようにしたとします。

  • タームごとに見出しをつける。子タームがある場合は親となるタームのすぐ下に見出しとして表示。
  • 子タームを持たないタームを設定した投稿は、タームタイトルのすぐ下に投稿を表示させる(子タームを持つタームで、親タームにのみを設定した投稿も同様)。
  • 親・子タームを設定した投稿は、子タームタイトルの下に投稿を表示させる(子タームのみを設定した場合も同様)。

実装の考え方

条件に基づいて下記の考え方で実装します。

  1. get_termsで特定タクソノミーのタームを取得してタームごとにforeach開始。
  2. (親)タームタイトルを表示。
  3. タームごとに子ターム取得(孫ターム・投稿記事を持たないタームを除外)。
  4. 子タームがある場合の処理。
    • A. 投稿記事を持つ子タームスラッグを除外用配列に格納(foreach内)。
    • B. 子タームを持つタームで、親タームにのみを設定した投稿のループ、除外用配列を使用。
    • C. 子タームを設定した投稿のループ(foreach内)。
  5. 子タームがない場合の処理。
  6. $postをリセット。
  7. foreach終了。

実際のコード

長くなるので、「実装の考え方」のリストに基づいて個別に記載します。

1. get_termsで特定タクソノミーのタームを取得してタームごとにforeach開始

子タームを除外してタームを取得後、foreachで回します。

<?php
    $target_post = '(投稿タイプのスラッグ)';
    $target_post_cat = '(タクソノミーのスラッグ)';
    $post_count = -1;
    $cat_args = array(
        'parent' => 0, //トップレベルのタームのみ
        'hierarchical' => 0 //子タームを含めない
    );
    $cats = get_terms($target_post_cat, $cat_args);
    foreach( $cats as $cat ):
?>

2. (親)タームタイトルを表示

はじめにタームのスラッグと名前を変数に格納しておいて、名前をタームタイトルとして表示します。

<?php
    $target_cat_slug = esc_html($cat -> slug);
    $target_cat_name = esc_html($cat -> name);
?>
<h3><?php echo $target_cat_name; ?></h3>

3. タームごとに子ターム取得(孫ターム・投稿記事を持たないタームを除外)

<?php $child_cats = get_terms($target_post_cat,'hierarchical=0&hide_empty=1&parent='.$cat -> term_id); ?>

4. 子タームがある場合の処理

<?php if( $child_cats ) : ?>

4-A. 投稿記事を持つ子タームスラッグを除外用配列に格納(foreach内)

<?php
    foreach( $child_cats as $child_cat  ){
        $exclude[] =  esc_html($child_cat->slug);
    }
?>

4-B. 子タームを持つタームで、親タームにのみを設定した投稿のループ、除外用配列を使用

<?php
    $args = array(
        'post_type' => $target_post,
        'tax_query' => array( //ここからタクソノミーのパラメーター
            'relation' => 'AND',
            array(
                'taxonomy' => $target_post_cat, //カスタム分類(カスタムタクソノミー)
                'field' => 'slug', //タクソノミータームの種類をスラッグで指定する
                'terms' => $target_cat_slug //タームからスラッグ取得 
            ),
            array(
                'taxonomy' => $target_post_cat, //カスタム分類(カスタムタクソノミー)
                'field' => 'slug', //タクソノミータームの種類をスラッグで指定する
                'terms' => $exclude, //除外タームスラッグ取得 
                'operator' => 'NOT IN' //除外
            )
        ),
        'post_status' => 'publish',
        'posts_per_page' => $post_count, // 表示するページ数
        'orderby' => 'menu_order', // 必要な場合に指定
        'order' => 'DESC' // 並び順
    );
    $my_query = new WP_Query($args);
?>
<?php if( $my_query->have_posts() ) : ?>
<ul>
    <?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
    <?php endwhile; ?>
</ul>
<?php endif; ?>

4-C. 子タームを設定した投稿のループ(foreach内)

<?php foreach( $child_cats as $child_cat ): ?>
<?php
    $child_cat_name = esc_html($child_cat -> name);
    $target_cat_slug = esc_html($child_cat->slug);
?>
<h4><?php echo $child_cat_name; ?></h4>
<?php
    $args = array(
        'post_type' => array($target_post),
        'taxonomy' => $target_post_cat,
        'term' => $target_cat_slug,
        'post_status' => 'publish',
        'posts_per_page' => $post_count, // 表示するページ数
        'orderby' => 'menu_order',
        'order' => 'DESC' // 並び順
    );
    $my_query = new WP_Query($args);
?>
<?php if( $my_query->have_posts() ) : ?>
<ul>
    <?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
    <?php endwhile; ?>
</ul>
<?php endif; ?>
<?php endforeach; ?>

子タームがない場合の処理

<?php else: ?>
<?php
    $args = array(
        'post_type' => array($target_post),
        'taxonomy' => $target_post_cat,
        'term' => $target_cat_slug,
        'post_status' => 'publish',
        'posts_per_page' => $post_count, // 表示するページ数
        'orderby' => 'menu_order',
        'order' => 'DESC' // 並び順
    );
    $my_query = new WP_Query($args);
?>
<?php if( $my_query->have_posts() ) : ?>
<ul>
    <?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
    <?php endwhile; ?>
</ul>
<?php endif; ?>
<?php endif; ?>

6. $postをリセット

<?php wp_reset_postdata(); ?>

7. foreach終了

<?php endforeach; ?>

以上です。

Author

  • Shinichi Kuroda - 黒田晋一
  • 香川県高松市 - Takamatsu-shi, Kagawa, Japan.
  • Mail - info@studiobusstop.com