【WordPress】カスタム投稿タイプのアーカイブページを任意の順序で並び替える方法

【WordPress】カスタム投稿タイプのアーカイブページを任意の順序で並び替える方法 WordPress

WordPressでは、カスタム投稿タイプ(CPT)を導入することで、投稿・固定ページ以外にも用途に応じたコンテンツ管理が可能になります。しかし、アーカイブページでの並び順はデフォルトでは投稿日順になっていることが多く、任意の順序で表示したいケースではひと工夫が必要です。

この記事では、カスタムフィールドやメニュー順などを使って、カスタム投稿タイプのアーカイブページを自由な順番で並び替える方法を解説します。

スポンサーリンク

アーカイブの並び替えはpre_get_postsで制御する

WordPressでは、アーカイブページのクエリに対してpre_get_postsフックを使うことで、表示順の制御が可能です。以下の例では、カスタム投稿タイプ「product」をmenu_orderの昇順で並べ替える処理を実装しています。

functions.php:menu_orderで並び替え
function custom_archive_order($query) {
  if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
    $query->set('orderby', 'menu_order');
    $query->set('order', 'ASC');
    $query->set('posts_per_page', -1); // 必要に応じて制限
  }
}
add_action('pre_get_posts', 'custom_archive_order');

このコードをfunctions.phpに追加すれば、「product」のアーカイブページはmenu_orderに従って表示されるようになります。

管理画面で並び順を設定するには

menu_orderを使うためには、管理画面で値を設定できるようにする必要があります。投稿編集画面でドラッグ&ドロップで並び替えたい場合は、「Intuitive Custom Post Order」などのプラグインが便利です。

あるいは、カスタムフィールドやACF(Advanced Custom Fields)を使って独自の並び順を設定し、meta値で制御することも可能です。

functions.php:カスタムフィールドの数値で並び替え(シンプル版)
function custom_archive_order_by_meta($query) {
  if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
    $query->set('meta_key', 'display_order');
    $query->set('orderby', 'meta_value_num');
    $query->set('order', 'ASC');
  }
}
add_action('pre_get_posts', 'custom_archive_order_by_meta');

この例では、カスタムフィールド「display_order」の数値で昇順に並び替えています。全ての商品に必ずdisplay_orderを設定する運用であれば、このシンプルな書き方で問題ありません。

メタキー未設定の投稿がアーカイブから消える
meta_keyを指定してorderby => 'meta_value_num'(またはmeta_value)で並び替えると、WordPressは内部的にpostmetaテーブルとINNER JOINします。このため、指定したメタキー(display_order)を持たない投稿は検索結果から完全に除外されてしまいます。新しく商品を追加した際にdisplay_orderの設定を忘れると、その商品がアーカイブページから静かに消えてしまう危険な落とし穴です。

この問題を避けるには、meta_queryに単純にEXISTS/NOT EXISTSのOR条件を追加するだけでは不十分です。WordPressコアの仕様上、トップレベルのmeta_key指定は明示的なmeta_queryと常にAND結合されてしまうため(WP_Meta_Query::parse_query_vars()で確認)、meta_keyを残したままではdisplay_order必須の条件が生き残ってしまいます。正しくは、トップレベルのmeta_key/orderby => 'meta_value_num'を使わず、名前付きmeta_queryクラス(WordPress 4.2で追加された機能)を使ってorderbyから直接参照します。

functions.php:全投稿を含めつつ数値で並び替え(正しい実装)
function custom_archive_order_by_meta($query) {
  if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
    // 名前付きmeta_queryクラス(order_clause)を使うことで、
    // トップレベルのmeta_key指定によるレガシー互換の強制AND結合を回避する
    $query->set('meta_query', array(
      'relation' => 'OR',
      'order_clause' => array(
        'key'     => 'display_order',
        'compare' => 'EXISTS',
        'type'    => 'NUMERIC',
      ),
      array(
        'key'     => 'display_order',
        'compare' => 'NOT EXISTS',
      ),
    ));
    // orderbyでクラス名(order_clause)を直接参照して並び替える
    $query->set('orderby', array('order_clause' => 'ASC'));
  }
}
add_action('pre_get_posts', 'custom_archive_order_by_meta');

この書き方であれば、meta_queryの全体がOR結合されたLEFT JOINになるため、display_orderを持たない投稿も除外されずに含まれます。ただし、MySQLの既定の並び順ではNULLは昇順(ASC)で先頭に来るため、display_order未設定の商品は一覧の先頭に表示される点に注意してください(末尾にしたい場合は、投稿保存時にデフォルト値を自動設定しておくなど別の対策が必要です)。

投稿タイプ登録時にsupportsへpage-attributesを追加

menu_orderを使うには、カスタム投稿タイプの登録時にpage-attributesを有効にしておく必要があります。

functions.php:page-attributesサポートを追加
register_post_type('product', array(
  'label' => '商品',
  'public' => true,
  'has_archive' => true,
  'supports' => array('title', 'editor', 'thumbnail', 'page-attributes'),
));

page-attributesを指定することで、「表示順(menu_order)」が投稿編集画面の右側に表示されます。

orderbyに対応する値一覧

WordPressのorderbyに指定できる主な値は以下のとおりです。

  • date:投稿日時
  • title:投稿タイトル
  • menu_order:表示順
  • meta_value:カスタムフィールド(文字列)
  • meta_value_num:カスタムフィールド(数値)

表示したい順序に合わせて最適な並び順を選びましょう。

よくある質問(FAQ)

Qカスタム投稿タイプのアーカイブページのソート順を変更するには?
Apre_get_postsフックでis_post_type_archive(‘custom_type’)とis_main_query()を確認し、$query->set(‘orderby’, ‘meta_value’)や$query->set(‘order’, ‘ASC’)を設定します。
Qメニュー順(menu_order)でアーカイブを並び替えるには?
Aregister_post_type()のsupports配列に’page-attributes’を含め、各記事の編集画面に表示される「順序」フィールドに数値を設定します。pre_get_postsでorderby=menu_orderとorder=ASCを設定します。
Qメタキーを持たない投稿も除外せずに数値でソートするには?
Aトップレベルのmeta_keyは明示的なmeta_queryと常にAND結合されるため使えません。meta_queryに名前付きクラス(例: ‘order_clause’ => array(‘key’=>’field’, ‘compare’=>’EXISTS’, ‘type’=>’NUMERIC’))とNOT EXISTS句をrelation=>’OR’で並べ、orderbyでその名前(order_clause)を直接参照します。

まとめ

カスタム投稿タイプのアーカイブページを任意の順序で並べ替えるには、pre_get_postsを利用してorderbyやmeta_keyを設定する方法が基本です。用途に応じて、menu_orderやカスタムフィールドを使い分けることで、柔軟な表示順制御が可能になります。カスタムフィールドで並び替える場合、全投稿に必ず値が設定されているとは限らないなら、名前付きmeta_queryクラスを使って除外を防ぎましょう。

また、管理画面での入力性を高めるために、ACFや並び替え用プラグインの導入も併せて検討すると効率的です。