べんりワザ・WordPressのテンプレートと投稿の取得

tax_queryでカテゴリ・タクソノミーで絞りこむ

カスタムタクソノミーの特定タームだけを一覧に出すtax_queryの書き方。field・operator・relationの意味、複数条件のAND/OR、絞りこみが効かないときの原因をコード付きでまとめました。

「冬の商品だけ一覧に出したい」——カスタムタクソノミーのタームで絞りこむのがtax_queryです。基本の形はこれだけ覚えれば足ります。

<?php
$query = new WP_Query([
  'post_type' => 'shohin',
  'tax_query' => [
    [
      'taxonomy' => 'season',   // タクソノミー名
      'field'    => 'slug',     // termsに何を渡すか
      'terms'    => 'winter',   // 対象のターム
    ],
  ],
]);
?>

tax_queryは「配列の中に条件の配列を入れる」二重構造です。ここが最初の関門なので、まず形に目を慣らしておくと迷いません。

テーマ開発カスタム投稿タイプで「商品」を作るカスタム投稿タイプとタクソノミーの作り方から知りたいときはこちら

3つのキーの意味

キー役割指定できる値
taxonomyどのタクソノミーかregister_taxonomy()で登録したスラッグ(category / post_tagも可)
fieldtermsに何を渡すか'slug' / 'term_id'(既定)/ 'name'
terms対象のターム単体または配列
operator条件の向き'IN'(既定)/ 'NOT IN' / 'AND' / 'EXISTS' / 'NOT EXISTS'

operatorの使い分け

// 冬または春(どちらかが付いている)
[
  'taxonomy' => 'season',
  'field'    => 'slug',
  'terms'    => ['winter', 'spring'],
  'operator' => 'IN',        // 既定
],

// 冬以外
[
  'taxonomy' => 'season',
  'field'    => 'slug',
  'terms'    => 'winter',
  'operator' => 'NOT IN',
],

// 冬と限定の両方が付いているものだけ
[
  'taxonomy' => 'season',
  'field'    => 'slug',
  'terms'    => ['winter', 'limited'],
  'operator' => 'AND',
],

// seasonが何か付いているものすべて
[
  'taxonomy' => 'season',
  'operator' => 'EXISTS',
],

termsを配列にしたときのINANDの違いが実務でよく効きます。「どれか1つでも」ならIN、「ぜんぶ付いている」ならANDです。

複数のタクソノミーを組み合わせる

条件を2つ以上並べ、relationでつなぎ方を決めます。

<?php
$query = new WP_Query([
  'post_type' => 'shohin',
  'tax_query' => [
    'relation' => 'AND',   // 両方満たすものだけ
    [
      'taxonomy' => 'season',
      'field'    => 'slug',
      'terms'    => 'winter',
    ],
    [
      'taxonomy' => 'brand',
      'field'    => 'slug',
      'terms'    => ['shimaenaga', 'kotori'],
    ],
  ],
]);
?>
  • 'relation' => 'AND'——すべての条件を満たす(省略時もこれ)
  • 'relation' => 'OR'——どれか1つでも満たす

カテゴリ・タグなら専用の引数が短い

標準のカテゴリとタグには、もっと短い書き方が用意されています。単純な絞りこみならこちらで十分です。

'category_name' => 'news',          // カテゴリのスラッグ
'category__in'  => [3, 7],          // カテゴリID
'tag'           => 'sale',          // タグのスラッグ
'tag__in'       => [12],            // タグID

tax_queryが必要になるのは、カスタムタクソノミーを使うときと、NOT INやANDのような細かい条件、複数タクソノミーの組み合わせが要るときです。

実例:今見ているタームで絞る

タクソノミーのアーカイブページで、そのタームの投稿を条件付きで出したい場合です。

<?php
$term = get_queried_object();   // 今表示しているターム
$query = new WP_Query([
  'post_type' => 'shohin',
  'tax_query' => [
    [
      'taxonomy' => $term->taxonomy,
      'field'    => 'term_id',
      'terms'    => $term->term_id,
    ],
  ],
  'posts_per_page' => 12,
]);
?>

get_queried_object()は「今のページの主役」を返す関数で、タクソノミーアーカイブならタームオブジェクトが返ります。

実例:同じタームの投稿を関連記事として出す

<?php
$terms = wp_get_post_terms(get_the_ID(), 'season', ['fields' => 'ids']);
$related = new WP_Query([
  'post_type'      => 'shohin',
  'post__not_in'   => [get_the_ID()],
  'posts_per_page' => 4,
  'tax_query'      => [
    [
      'taxonomy' => 'season',
      'field'    => 'term_id',
      'terms'    => $terms,
    ],
  ],
]);
?>

wp_get_post_terms()['fields' => 'ids']を渡すとIDの配列が返るので、そのままtermsに入れられます。

べんりワザ関連記事をプラグインなしで出す関連記事のパターンをもっと知りたいときはこちら

カスタムフィールドの条件と組み合わせる

tax_querymeta_queryは同時に使えます。「冬の商品で、在庫ありのものだけ」といった絞りこみです。

'tax_query'  => [['taxonomy' => 'season', 'field' => 'slug', 'terms' => 'winter']],
'meta_query' => [['key' => 'stock', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC']],
べんりワザmeta_queryでカスタムフィールドで絞る・並べ替えるmeta_queryの書き方と並べ替えはこちら

まとめ

  1. tax_query配列の中に条件の配列を入れる二重構造。taxonomy / field / termsの3点セット
  2. スラッグを渡すなら'field' => 'slug'が必須(既定はterm_id)
  3. operatorIN / NOT IN / ANDを切り替え、複数条件はrelationでつなぐ
  4. 標準のカテゴリ・タグはcategory_nametagのほうが短い。効かないときは名前をvar_dumpで確認

絞りこみが自在になると、同じ投稿データから何種類もの一覧を作れるようになります。

よくある質問

tax_queryのfieldには何を指定すればいいですか?
termsに何を渡すかで決めます。スラッグ('winter'など)を渡すなら'slug'、ID(数値)を渡すなら'term_id'、名前を渡すなら'name'です。既定はterm_idなので、スラッグを渡すときはfieldの指定が必須です。
複数のタクソノミーで絞りこむには?
tax_queryの配列に条件を2つ以上並べ、'relation' => 'AND'(両方満たす)または'OR'(どちらか)を指定します。relationを省略するとANDになります。
カテゴリやタグにもtax_queryを使えますか?
使えます。taxonomyに'category'または'post_tag'を指定します。ただし単純な絞りこみならcategory_nameやtagという専用の引数のほうが短く書けます。
tax_queryが効かず全件出てしまいます
タクソノミー名(register_taxonomyで登録したスラッグ)とタームのスラッグが正しいか確認します。存在しない名前を書くと条件が無視されて全件表示になります。get_taxonomies()やget_termsで実際の名前を確認してください。