CommentOut

WP_Queryのtax_queryとmeta_queryの使い方 WP_Queryのtax_queryとmeta_queryの使い方

WP_Queryのtax_queryとmeta_queryの使い方

公開日:  最終更新日:

WordPressで記事の絞り込みをする時に出てくるWP_Queryですが、様々な設定があって、取っ付きづらいと感じることもあるかもしれません。
しかし、設定内容を理解すれば、実はさほど難しいものではありません。

また、WP_Queryが使えると、Welcartの商品ページも記事として管理されていますし、施工事例をカスタム投稿として登録した時にも、記事としてWP_Queryで絞り込み表示や並べ替え表示ができるようになります。

WP_Queryを使用する上で、特にややこしいのが、tax_queryとmeta_queryなので、その2点を説明します。

tax_queryもmeta_queryもWordPressで記事を絞り込んで取得する時に使用する

tax_queryもmeta_queryも対象となる値が違うだけで、記事の絞り込みに使用します。

tax_queryはカスタム投稿をタクソノミーで絞り込みを行う時に使う

tax_queryはカスタム投稿タイプの記事をタクソノミーでの絞り込む時に使用します。

通常の”投稿”はタクソノミーではなく、カテゴリーですよね。
WP_Queryを使って、カテゴリーで絞り込む時はcatやcategory_nameなどで絞り込みしますよね。
カテゴリーでの絞り込みを実際に記述すると以下のようになります。

<?php $result = new WP_Query(array(
    'post_type' => 'post',
    'category_name' => 'news'
)); ?>

しかし、これはあくまでも”投稿”のカテゴリーを絞り込む方法であって、カスタム投稿タイプのタクソノミーでは有効ではありません。

カスタム投稿タイプのタクソノミーで絞り込む時には、tax_queryを使用します。

<?php $result = new WP_Query(array(
    'post_type' => 'news',
    'tax_query' => array(
        array(
            'taxonomy' => 'menu_category',
            'field' => 'slug',
            'terms' => 'event'
        ),
    ),
)); ?>

カスタム投稿タイプ:ニュース(news)のタクソノミー:ニュースカテゴリー(news_category)の中で、ターム:イベント(event)を条件にして絞り込む時は上記のようになります。

tax_queryにarray()が二重(2次元配列)で入っている点に注意です。

ちなみに、複数タームを条件にすることも出来ます。

tax_queryを使って、複数タームをAND条件で絞り込む方法

カスタム投稿タイプなら以下の通り

<?php $result = new WP_Query(array(
    'post_type' => 'news',
    'tax_query' => array(
        array(
            'taxonomy' => 'menu_category',
            'field' => 'slug',
            'terms' => array('event', 'lecture'),
            'operator' => 'AND',
        ),
    ),
)); ?>

カスタム投稿タイプのタームにイベント(event)と講演(lecture)の両方が設定されている記事

投稿だったら以下の通り

<?php $result = new WP_Query(array(
    'post_type' => 'post',
    'category__and' => array('event', 'lecture'),
)); ?>

投稿カテゴリーのイベント(event)と講演(lecture)の両方が設定されている記事

tax_queryを使って、複数タームをOR条件で絞り込む方法

カスタム投稿タイプなら以下の通り

<?php $result = new WP_Query(array(
    'post_type' => 'news',
    'tax_query' => array(
        array(
            'taxonomy' => 'menu_category',
            'field' => 'slug',
            'terms' => array('event', 'lecture'),
            'operator' => 'IN',
        ),
    ),
)); ?>

カスタム投稿タイプのタームにイベント(event)と講演(lecture)のいずれかが設定されている記事

投稿だったら以下の通り

<?php $result = new WP_Query(array(
    'post_type' => 'post',
    'category__in' => array('event', 'lecture'),
)); ?>

投稿カテゴリーのイベント(event)と講演(lecture)のいずれかが設定されている記事

カスタム投稿タイプを絞り込む時もAND条件はandなのですが、OR条件は『in』になっている点に注意です。

カスタムフィールドで記事を絞り込む時はmeta_queryを使用する

タクソノミーでの絞り込みはtax_queryを使用しましたが、カスタムフィールドで絞り込む時にはmeta_queryを使用します。
このmetaっていうのは、記事情報に紐づくメタデータを条件に記事の絞り込みを行うので、meta_queryという名前になっています。カスタムフィールドも記事に紐づくメタデータなんですよね。

<?php $result = new WP_Query(array(
    'post_type' => 'news'
    'meta_query' => array(
        array(
            'key' => '',
            'value' => '',
            'compare' => '=',
        )
    ),
)); ?>

このmeta_queryはかなり複雑な条件での絞り込みにも対応しており、ゴリゴリにテーマを改造する人などは使用機会が多いと思います。
ただし、使用時に注意点もいくつかあって、間違えると正しい記事が取得できなくて、時間を無駄にすることになるので、以下の注意点を覚えておいてください。

カスタムフィールドのタイプによっては、compareを変更する必要がある

例えば、先ほどの’compare’ => ‘=’っていうのは、完全一致なので、文字列部分一致で検索する場合には、compareを’compare’ => ‘LIKE’に変更する必要があります。

また、カスタムフィールドがラジオボタンであれば1つしか選択できないため、値は1つですが、チェックボックスの場合は複数選択される可能性があるため、データベースには値が配列形式で保存されます。
そのため、カスタムフィールドがチェックボックスになっている場合は’compare’ => ‘=’では正しい記事を取得できません。

meta_queryで文字列の部分一致を条件に記事を取得する場合

例えば、以下のようなテキストエリアタイプのカスタムフィールドを設定した場合

『商品情報』というカスタム投稿タイプを定義しておきます。
(※今回は検証用に定義しているだけなので、WelcartやWooCommerceではありません。)

そして、商品のカスタムフィールドを登録します。

こんなもんで良いでしょう。

そして、テンプレートに記事情報の取得スクリプトを記述します。

<?php
$result = new WP_Query(array(
    'post_type' => 'products',
    'meta_query' => array(array(
        'key' => 'exp',
        'value' => 'キャスケット',
        'compare' => '=',
    )),
));
if ($result->have_posts()): while($result->have_posts()): $result->the_post(); ?>
    <div>
        <a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a>
    </div>
<?php endwhile; else: ?>
    <p>一致する記事は見つかりませんでした。</p>
<?php endif; ?>

今回はカスタムフィールド”exp”に対して、「キャスケット」という文字に一致する記事を取得したい
‘compare’ => ‘=’になっている点に注目です。
compareを指定しなかった場合も、デフォルトは’=’です。

その結果が以下の通りです。

‘compare’ => ‘=’は完全一致なので、条件に一致しなくなってしまうんです。

そこで部分一致(LIKE)に変更します。

<?php
$result = new WP_Query(array(
    'post_type' => 'products',
    'meta_query' => array(array(
        'key' => 'exp',
        'value' => 'キャスケット',
        'compare' => 'LIKE',
    )),
));
if ($result->have_posts()): while($result->have_posts()): $result->the_post(); ?>
    <div>
        <a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a>
    </div>
<?php endwhile; else: ?>
    <p>一致する記事は見つかりませんでした。</p>
<?php endif; ?>

compareを’LIKE’に変更するだけです。
その結果が以下の通りです。

ちゃんと条件に一致するようになったので、記事が取得できています。

meta_queryでチェックボックスを条件に記事を取得する場合

チェックボックスも落とし穴の一つです。
例えば、以下のように選択フィールドとラジオボタンフィールドとチェックボックスフィールドのカスタムフィールドをそれぞれ設定します。

選択フィールド

ラジオボタンフィールド

チェックボックスフィールド

選択フィールドとラジオボタンフィールドは基本的に単一選択、チェックボックスは複数選択が可能になっています。

先ほどの商品01(帽子)に以下のような値を設定しておきます。

さて、ここでデータベースにはどのように値が設定されているか確認しておきましょう。

選択フィールドとラジオボタンフィールドは値がそのままレコードに登録されていますが、複数選択可能なチェックボックスフィールドでは保存形式が異なります。

このような形でデータが保存されているので、選択フィールドとラジオボタンフィールドでは、’compare’ => ‘=’を使うことが出来ます。
例えば、以下のような記述で、記事データを取得することが出来ます。

<?php
$result = new WP_Query(array(
    'post_type' => 'products',
    'meta_query' => array(array(
        'key' => 'parts',
        'value' => '頭',
        'compare' => '=',
    )),
));
if ($result->have_posts()): while($result->have_posts()): $result->the_post(); ?>
    <div>
        <a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a>
    </div>
<?php endwhile; else: ?>
    <p>一致する記事は見つかりませんでした。</p>
<?php endif; ?>

ただし、チェックボックスフィールドでは話が違います。
チェックボックスフィールドの値で記事を絞り込みたい時には、上記のような記述では、テキスト比較の時と同様、完全一致なので条件に一致せず、正しい記事データを取得することができません。

<?php
$result = new WP_Query(array(
    'post_type' => 'products',
    'meta_query' => array(array(
        'key' => 'age',
        'value' => '10代',
        'compare' => 'LIKE',
    )),
));
if ($result->have_posts()): while($result->have_posts()): $result->the_post(); ?>
    <div>
        <a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a>
    </div>
<?php endwhile; else: ?>
    <p>一致する記事は見つかりませんでした。</p>
<?php endif; ?>

一応、’compare’ => ‘LIKE’を使うと部分一致になるので、目的の記事データを取得することが出来ます。

ただし、ここでも注意点があります。
それはカスタムフィールドの設定で、値とラベルをそれぞれ設定した時です。
以下のような設定を行ったとします。

上記の設定で『10代』が選ばれている記事を取得したいとします。
『10代』のラベルが設定されている値『a』か『1』を条件に記事データを取得します。

<?php
$result = new WP_Query(array(
    'post_type' => 'products',
    'meta_query' => array(array(
        'key' => 'age',
        'value' => 'a',
        'compare' => 'LIKE',
    )),
));
if ($result->have_posts()): while($result->have_posts()): $result->the_post(); ?>
    <div>
        <a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a>
    </div>
<?php endwhile; else: ?>
    <p>一致する記事は見つかりませんでした。</p>
<?php endif; ?>

さて、これで絞り込まれるかというと、絞り込めないんです。
データベースに保存された値をよく見てください。

選択肢とは全く関係のない部分に『a』や『1』という値が入っているので、ここが部分一致してしまいます。
なので、値とラベルを別々に設定する場合は1文字やアルファベットや数字ではなく、意味のある単語や商品コードのような複数桁の文字列を登録するようにしましょう。

複数のカスタムフィールドを絞り込み条件にする方法

カスタムフィールドを条件に記事を絞り込む時には、条件が1つじゃないことって結構多いんじゃないかなと思います。
例えば、投稿を商品紹介ページとして使用していて、『今日が発売日より後で、廃番フラグがONになっていないページ』などを条件に記事を絞り込んだり、『対象年齢が”子ども”、尚且つ、アレルギー項目に”卵”が含まれないページ』などを条件に記事を絞り込んだり、そういう条件指定ってあると思います。
そういう時にも、meta_queryは活躍してくれます!

例えば、先ほどのカスタムフィールドを活用して、シーズン『秋冬』の『20代』向け商品を絞り込み表示したいとします。
その場合、以下のように記述します。

<?php
$result = new WP_Query(array(
    'post_type' => 'products',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'season',
            'value' => '秋冬',
            'compare' => '=',
        ),
        array(
            'key' => 'age',
            'value' => '20代',
            'compare' => 'LIKE',
        )
    ),
));
if ($result->have_posts()): while($result->have_posts()): $result->the_post(); ?>
    <div>
        <a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a>
    </div>
<?php endwhile; else: ?>
    <p>一致する記事は見つかりませんでした。</p>
<?php endif; ?>

これまでのmeta_queryの配列が2種類になり、1次元目に’relation’という値が追加されました。
これはmeta_queryの条件が2種類となり、それらの条件がAND条件なのか、OR条件なのかを明示するために追加されています。

このように、meta_queryは結構複雑に組み合わせることができ、WordPressの記事一覧表示の自由度を大きく広げることのできる可能性を秘めた物となっています。
ぜひマスターしておきましょう!

宣伝
WordPressサイトのテンプレート編集やトラブル対応、バグ修正、簡単なJavascriptの作成(カルーセルやバリデーション等)など、小規模なスポット対応を受け付けております。
もしお困りごとがありましたら、お問い合わせフォームよりご相談ください。

この記事を書いた人

uilou

uilou

プログラマー

基本的に、自分自身の備忘録のつもりでブログを書いています。 自分と同じ所で詰まった人の助けになれば良いかなと思います。 システムのリファクタリングを得意としており、バックエンド、フロントエンド、アプリケーション、SQLなど幅広い知識と経験があります。 広いだけでなく、知識をもっと深堀りしていきたいですね。