WordPress タクソノミー順にカスタム投稿(の、ひとかたまり)を順番に表示する方法
カスタム投稿の記事一覧を表示するときに、各記事に紐づいているカスタムタクソノミー(カテゴリ的なもの)を、”ひとかたまり”ごとに順番に表示する方法が、なにげにわからなかったので調べてみました。
どういうことか
ちょっと説明がややこしいのですが、このニーズって結構あるんじゃないかと思うのですが簡単に言えば以下のようなことです。
※あえてタクソノミーを「カテゴリー」と記載していますが要はこういうことです。
※「カテゴリA」「カテゴリB」..の文字は、実際は表示せず記事を出すイメージ
カテゴリーA
- 記事
- 記事
- 記事
カテゴリーB
- 記事
- 記事
- 記事
カテゴリーC
- 記事
- 記事
- 記事
表示(記事)数が少ない場合
記事数が少ない場合であれば、ここで説明されているように以下のコードでイケるかと思います。
<?php
$args = array(
'parent' => 0,
'hierarchical' => 0,
'orderby' => 'term_order', // Category Order and Taxonomy Terms Order を使用
'order' => 'ASC'
);
$taxonomy_name = 'taxonomy_slug';//タクソノミー名
$taxonomys = get_terms($taxonomy_name, $args);
if(!is_wp_error($taxonomys) && count($taxonomys)):
foreach($taxonomys as $taxonomy):
$url = get_term_link($taxonomy->slug, $taxonomy_name);
$tax_posts = get_posts(array(
'post_type' => 'brand',
'posts_per_page' => -1, // 表示させたい記事数
'tax_query' => array(
array(
'taxonomy' => 'season',
'terms' => array( $taxonomy->slug ),
'field' => 'slug',
'include_children' => true,
'operator' => 'IN'
),
array(
'taxonomy' => 'season',
'terms' => 'spring',
'field' => 'slug',
'operator' => 'NOT IN'
),
'relation' => 'AND'
)
));
if($tax_posts):
?>
<h2 id="<?php echo esc_html($taxonomy->slug); ?>" class=""><a href="<?php echo $url; ?>"><?php echo esc_html($taxonomy->name); ?></a></h2>
<ul>
<?php foreach($tax_posts as $tax_post): ?>
<!--ループで表示したい内容-->
<li>
<span class="thumb">
<a href="<?php echo get_permalink($tax_post->ID); ?>">
<?php
if(has_post_thumbnail($tax_post->ID)) {
echo get_the_post_thumbnail($tax_post->ID,'post-thumbnail'); }
?>
</a>
</span>
<span class="title"><?php echo get_the_title($tax_post->ID); ?></span>
</li>
<!--/ループで表示したい内容-->
<?php endforeach; ?>
</ul>
<?php endif; endforeach; endif; ?>
(前提として、「Category Order and Taxonomy Terms Order」というプラグインでタクソノミーの表示順を決めています。)上記でやっていることは、まず、その順番にタクソノミーを取り出します。(9行目のget_terms)、
そして取り出したタクソノミーに該当する記事一覧を取得し表示します(13行目のget_posts以下)
ここで重要なのは、「orderby」に「term_order」という文字列を設定します(以下)
こうすることで「Category Order and Taxonomy Terms Order」プラグインの管理画面で設定した順番が反映されたタクソノミー一覧を取得できます。
$args = array(
'parent' => 0,
'hierarchical' => 0,
'orderby' => 'term_order',
'order' => 'ASC'
);
$taxonomy_name = 'taxonomy_slug';//タクソノミー名
$taxonomys = get_terms($taxonomy_name, $args);
この方法は、固定ページなど1ページ内で済む場合であれば良いのですが、
ページをまたいで表示するような、もっと記事が多い場合はちょっと難しくなってきます。
表示(記事)数が多い場合(ページをまたぐような場合)
タクソノミーの順番を設定するのは上と同様、「Category Order and Taxonomy Terms Order」プラグインで設定します。ただ、今回の場合は先のtax_queryに渡すためにidの一覧を取得します。
pre_get_posts
今回の場合は、pre_get_postsでループ条件を設定する方法で実装します。 なので、functions.php内に以下のようなコードを記述します。
add_action( 'pre_get_posts', 'custom_pre_get_posts' );
function custom_pre_get_posts( $obj ) {
if ( is_admin() || !$obj->is_main_query() ){
return;
}
//ここから処理を書いていきます
$taxonomy_list = get_terms(array(
'fields' => 'ids', //記事のIDをfieldsに
'taxonomy' => 'taxonomy_slug',//タクソノミー名
'orderby' => 'term_order',//Category Order and Taxonomy Terms Orderの順番で
'hide_empty' => false,
));
//posts_orderbyをフィルタ。処理を別関数で。
add_filter('posts_orderby', 'custom_orderby');
//記事数などを設定
$obj->set('posts_per_page', -1);
//tax_queryに設定
$obj->set('tax_query', array(
array(
'taxonomy' => 'taxonomy_slug',
'field' => 'term_id',
'terms' => $taxonomy_list
)
));
return;
}
posts_orderbyをフィルタ
function custom_orderby($orderby_statement) {
$orderby_statement = " wp_term_relationships.term_taxonomy_id ASC, ".$orderby_statement;
return $orderby_statement;
}
posts_orderbyのフィルタ関数をfunctions.php内に追記し、SQL文を直接操作します。上記ではデータベースのwp_term_relationshipsテーブルのterm_taxonomy_id列をASCでソートする記述を既存のSQL文に追記しています。
あとはページ側でループ
あとは該当するタクソノミーアーカイブページで、ループするだけでタクソノミーごとの記事が出てくると思います。<?php while ( have_posts() ) : the_post(); ?> <?php endwhile; ?>
