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; ?>
ご依頼・お問い合わせ