2018年4月10日に加筆・修正をしました。
製品やサービスの記事一覧の表示は、新着順ではなくカテゴリ別で表示するのが自然です。カテゴリに親子関係がある場合は、子カテゴリ別記事一覧ページのリンク階層が深くならないよう、工夫をすると記事全体の見通しが良くなります。今回はあるカスタム投稿に特定タクソノミーの親子タームを設定した場合を前提に、リスト形式で記事一覧を表示する方法について触れます。
アーカイブページの場合
archive-( タクソノミースラッグ ).phpに、ターム別記事一覧用の記述をします。
表示の条件
表示の条件は下記のようにしたとします。
- タームごとに見出しをつける。子タームがある場合は親となるタームのすぐ下に見出しとして表示。
- 子タームを持たないタームを設定した記事は、タームタイトルのすぐ下に表示させる(子タームを持つタームで、親タームにのみを設定した投稿も同様)。
- 親・子タームを設定した記事は、子タームタイトルの下に表示させる(子タームのみを設定した場合も同様)。
実装の考え方
条件に基づいて下記の考え方で実装します。
- get_termsで特定タクソノミーのタームを取得してタームごとにforeach開始。
- 親タームタイトルを表示。
- タームごとに子ターム取得(孫ターム・投稿記事を持たないタームを除外)。
- 子タームがある場合の処理。
- A. 投稿記事を持つ子タームスラッグを除外用配列に格納(foreach内)。
- B. 子タームを持つタームで、親タームにのみを設定した投稿のループ、除外用配列を使用。
- C. 子タームを設定した投稿のループ(foreach内)。
- 子タームがない場合の処理。
- $postをリセットして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をリセットしてforeach終了
<?php wp_reset_postdata(); ?>
<?php endforeach; ?>
タクソノミーページの場合
ご要望がありましたので追記しました。
taxonomy-( タクソノミースラッグ ).phpに、ターム別記事一覧用の記述をします。
表示の条件
表示の条件は下記のようにしたとします。
- 親タームの場合は子タームごとの記事一覧をサブループで表示。
- 子を持たないタームや子タームの場合は記事一覧をメインループで表示。
実装の考え方
条件に基づいて下記の考え方で実装します。
- タームタイトルの表示。
- 親ターム判定用の処理。
- 親タームの場合の処理。
- A. タームごとに子ターム取得(孫ターム・投稿記事を持たないタームを除外)。
- B. 子タームを設定した投稿をループ(foreach内)。
- C. $postをリセットしてforeach終了。
- 子を持たないタームや子タームの場合の処理。
実際のコード
アーカイブと同様に、「実装の考え方」のリストに基づいて個別に記載します。
1. タームタイトルの表示
<h2><?php single_term_title(); ?></h2>
2. 親ターム判定用の処理
<?php
$target_post_cat = '(タクソノミーのスラッグ)';
// 親ターム判定
$is_parent_term = get_term_children(get_queried_object_id(), $target_post_cat) ? true : false;
?>
使用関数:get term children
3. 親タームの場合の処理
<?php if($is_parent_term): ?>
3-A. タームごとに子ターム取得(孫ターム・投稿記事を持たないタームを除外)。
<?php
// 現在のタームの子ターム取得
$child_cats = get_terms($target_post_cat,'hierarchical=0&hide_empty=1&parent='.get_queried_object_id());
?>
使用関数:get terms
3-B. 子タームを設定した投稿をループ(foreach内)
<?php foreach( $child_cats as $child_cat ): ?>
<?php
$target_post = '(投稿タイプのスラッグ)';
$target_cat_name = esc_html($child_cat -> name);
$target_cat_slug = esc_html($child_cat -> slug);
$target_cat_url = esc_html(get_term_link( $child_cat ));
$post_count = -1;
$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' => 'ASC'
);
$my_query = new WP_Query($args);
?>
<?php if( $my_query->have_posts() ) : ?>
<h3><a href="<?php echo $target_cat_url; ?>"><?php echo $target_cat_name; ?></a></h3>
<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; ?>
3-C. $postをリセットしてforeach終了
<?php wp_reset_postdata(); ?>
<?php endforeach; ?>
子を持たないタームや子タームの場合の処理
<?php else : ?>
<?php if( $wp_query->have_posts() ) : ?>
<ul>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
リンク階層を浅くした一覧表示と期待される効果
- 見る人が製品・サービスを見渡せるようになる。
- 見る人が目的のページに辿り着きやすくなる。
- 子カテゴリページと製品・サービス詳細ページのSEO効果の向上が見込める(現在のGoogleのアルゴリズムの場合)。
以上です。