【WordPress】カスタムフィールドを含む複数の条件でソートをする方法

WordPress で投稿やカスタム投稿タイプを並べ替えるとき、デフォルトでは「日付」「タイトル」「ランダム順」などが一般的です。しかし、カスタムフィールド(メタ情報)を含めた複数の条件でソートしたい場合もあります。たとえば「独自の数値や順位をもとに昇順で並べ、そのあとに投稿日を降順に並べる」など、より柔軟な並び替えが必要なシーンもあるはずです。

本記事では、WordPress でカスタムフィールドを使った複数の条件によるソート方法について解説します。

スポンサーリンク

カスタムフィールドを使った複数ソートが必要なシーン

独自の並び順をつけたい時

管理画面やフロントエンドで、独自の優先度や数値をカスタムフィールドに保存し、その値を元に並べ替えたいケース。

複数のメタ情報と標準のタイトルや日付を組み合わせたい時

例:優先度(昇順)→ タイトル(昇順) → 日付(降順)というように、複雑な条件で並べ替える要望があるケース。

「標準のソートではできない柔軟な条件付けをしたい」── そんな時に、カスタムフィールドでの複数ソートが役立ちます。

基本のソート構文:WP_Query での orderby 配列指定

WordPress 4.0 以降は orderby に配列を設定できるので、下記のように複数の条件を連続して指定できます。カスタムフィールド(数値扱い)をまず昇順に並べ、そのあとに日付を降順で並べる例です。

単一のカスタムフィールド+日付でソート
$args = [
  'post_type'      => 'post',
  'posts_per_page' => -1,
  'meta_key'       => 'my_custom_key',
  'orderby'        => [
    'meta_value_num' => 'ASC',
    'date'           => 'DESC',
  ],
];
$query = new WP_Query( $args );
  • meta_key でソートしたいキー名を指定し、数値の場合は meta_value_num、文字列の場合は meta_value を使い分ける。
  • orderby は配列で渡すことで、第一優先→第二優先といった複数条件ソートが可能になる。

カスタムフィールドが複数ある場合

複数のカスタムフィールドを使いたい場合は、次のように meta_query でキーを指定し、それぞれをソート条件に含める必要があります。

NG:meta_queryの節に名前が無くorderbyと紐付かない
$args = [
  'post_type'      => 'post',
  'posts_per_page' => -1,
  'meta_query'     => [
    'relation' => 'AND',
    [
      'key'     => 'custom_field_a',
      'type'    => 'NUMERIC',
      'compare' => 'EXISTS',
    ],
    [
      'key'     => 'custom_field_b',
      'type'    => 'NUMERIC',
      'compare' => 'EXISTS',
    ],
  ],
  'orderby' => [
    'custom_field_a' => 'ASC',  // 節に名前が無いため紐付かない
    'custom_field_b' => 'DESC',
  ],
];
$query = new WP_Query( $args );
meta_queryの節にはorderbyと同じ名前(エイリアス)を付ける
複数のメタキーを条件にソートするには、meta_queryの各節に明示的な名前(配列キー)を付け、orderby側で同じ名前を参照する必要があります。メタキーの値(custom_field_aなど)をそのままorderbyのキーにしても、どの節に対応するか紐付かず、複数条件ソートが機能しません。
OK:meta_queryの節に名前を付けorderbyで同じ名前を参照
$args = [
  'post_type'      => 'post',
  'posts_per_page' => -1,
  'meta_query'     => [
    'relation' => 'AND',
    'field_a'  => [                  // 節に明示的な名前(エイリアス)を付ける
      'key'     => 'custom_field_a',
      'type'    => 'NUMERIC',
      'compare' => 'EXISTS',
    ],
    'field_b'  => [
      'key'     => 'custom_field_b',
      'type'    => 'NUMERIC',
      'compare' => 'EXISTS',
    ],
  ],
  'orderby' => [
    'field_a' => 'ASC',  // 第一優先(meta_queryの節名を参照)
    'field_b' => 'DESC', // 第二優先
  ],
];
$query = new WP_Query( $args );
  • type をしっかり指定しないと、正しい並び替えが期待できない場合がある(数字が文字列ソートされるなど)。
  • relation を AND にすることで、両方のフィールドが存在する投稿だけに限定できる。

テキストフィールドと数値フィールドを混在させたい場合

異なるタイプのカスタムフィールドを使う場合も、基本は同様です。たとえば「テキスト(文字列)をアルファベット順に並べた上で、数値フィールドを昇順に並べる」なら、下記のように設定します。

文字列フィールドと数値フィールドを組み合わせてソート
$args = [
  'post_type'      => 'post',
  'posts_per_page' => -1,
  'meta_query'     => [
    'relation'  => 'AND',
    'text_clause' => [
      'key'     => 'custom_text',
      'compare' => 'EXISTS',
      'type'    => 'CHAR',   // 文字列として扱う
    ],
    'number_clause' => [
      'key'     => 'custom_number',
      'compare' => 'EXISTS',
      'type'    => 'NUMERIC' // 数値として扱う
    ],
  ],
  'orderby' => [
    'text_clause'   => 'ASC',
    'number_clause' => 'ASC',
  ],
];
$query = new WP_Query( $args );

pre_get_posts フィルタを使って管理画面やアーカイブをカスタマイズ

pre_get_posts フィルタを使うと、管理画面やアーカイブページなど既存のクエリに対してソート条件を変更できます。たとえば、管理画面で特定の投稿タイプだけカスタムフィールドを優先してソートしたい場合は下記のように書きます。

functions.php:管理画面の一覧をカスタムフィールド優先でソート
function my_admin_sort_posts_by_custom_field( $query ) {
  if ( is_admin() && $query->is_main_query() ) {
    if ( 'my_post_type' === $query->get( 'post_type' ) ) {
      // カスタムフィールド優先
      $query->set( 'meta_key', 'order_key' );
      $query->set( 'orderby', [
        'meta_value_num' => 'ASC',
        'title'          => 'ASC',
      ] );
    }
  }
}
add_action( 'pre_get_posts', 'my_admin_sort_posts_by_custom_field' );

管理画面での絞り込みやカスタム投稿タイプの一覧画面など、既存の画面を柔軟にカスタマイズしたい時に便利です。

複雑なソートを成功させるポイント

meta_query と type の指定を忘れない

特に複数のカスタムフィールドを扱う場合は、meta_query の指定でデータベースに読み込むようにしておく必要があります。また、文字列なら CHAR、数値なら NUMERIC と適切に指定することが重要です。

パフォーマンスを考慮する

meta_query の数が増えると JOIN が増え、クエリが複雑になります。多量の投稿を扱うサイトではパフォーマンスに影響が出る場合があるため、専用のテーブルを用意するなどの検討が必要です。

特定の値を優先して表示するソート

カスタムフィールドが特定の値(例: custom_field_a = 'important')を持つ投稿を先頭に表示し、それ以外の投稿もその後に続けて表示したい場合があります。

post__inは「絞り込みフィルター」であることに注意
post__inは指定したIDの投稿だけを返すフィルターです。優先表示させたい投稿のIDだけをpost__inに渡すと、それ以外の投稿は結果から除外されてしまいます。「優先表示+残りの投稿も表示」を実現するには、全投稿のID配列を用意したうえで、優先させたいIDを先頭に並べ替えてからpost__inに渡す必要があります。
優先したい投稿を先頭に、残りの投稿もすべて表示する
// 通常の並び順で全投稿IDを取得
$all_ids = get_posts(array(
    'post_type'      => 'post',
    'posts_per_page' => -1,
    'orderby'        => 'date',
    'order'          => 'DESC',
    'fields'         => 'ids',
));

// 優先表示したい投稿のIDを取得(custom_field_a = 'important')
$important_query = new WP_Query(array(
    'post_type'      => 'post',
    'posts_per_page' => -1,
    'meta_key'       => 'custom_field_a',
    'meta_value'     => 'important',
    'fields'         => 'ids',
));
$important_ids = $important_query->posts;

// 優先ID + 残りのID(重複除外)で、完全な並び順を作る
$other_ids    = array_diff($all_ids, $important_ids);
$ordered_ids  = array_merge($important_ids, $other_ids);

$args = array(
    'post_type'      => 'post',
    'posts_per_page' => 10,
    'post__in'       => $ordered_ids,
    'orderby'        => 'post__in', // $ordered_idsの並び順をそのまま使う
);
$query = new WP_Query($args);

これにより、custom_field_aの値がimportantの投稿が先頭に表示され、それ以外の投稿もその後に続けて表示されます。post__inに渡すID数が非常に多いサイトでは、クエリの負荷が増える点に留意してください。

関連記事

よくある質問(FAQ)

Qカスタムフィールドに格納した日付文字列(YYYY-MM-DD)でソートするには?
Ameta_key=’date_field’とorderby=’meta_value’を設定します。YYYY-MM-DD形式の文字列は辞書順と時系列が一致するため、meta_value(文字列ソート)で正しく並びます。
Qカスタムフィールドに格納した数値でソートする際の注意点は?
A必ずmeta_value_num(数値ソート)を使います。meta_value(文字列ソート)では1・10・2の順になります。meta_typeにNUMERICやDATEを指定することもできます。複数のフィールドを同時にソート条件にする場合は、meta_queryの各節に名前を付けてorderbyで同じ名前を参照する必要がある点にも注意してください。
Qカスタムフィールドの値が入っていない記事も含めてソートするには?
Ameta_queryのrelation=’OR’でNOT EXISTSの条件も追加するか、LEFT JOINを使ったカスタムSQLクエリが必要です。posts_joinとposts_whereフィルターで実装する方法があります。

まとめ

WordPress でカスタムフィールドを含む複数の条件でソートを行う方法は、以下のステップが基本です。

  1. 単一ソート なら meta_key と orderby に meta_value or meta_value_num を設定。
  2. 複数ソート するなら、meta_query の各節に名前(エイリアス)を付け、orderby で同じ名前を参照する。
  3. 管理画面など既存クエリ をカスタマイズしたい時は pre_get_posts を活用。

こうした設定を組み合わせることで、柔軟なソートを実現できます。並び順はユーザーの使い勝手や運用効率にも大きく影響するため、ぜひ自分のサイトの要件に合わせて最適なソートロジックを組んでみてください。