かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

WordPress WP_Query 複数のカスタムフィールドを条件に投稿を取得したい。

WordPressでカスタムフィールドをたくさん作ったサイトとかでは、カスタムフィールドの値を条件にして投稿を取得したいケースが多々あります。
複数のカスタムフィールドの値を条件に投稿を取得する時のメモ。

条件にするカスタムフィールドが1つのとき

おさらい。
例えば product 投稿のカスタムフィールド pickuponのものを取得したい場合。
meta_key キーワードを使って指定する方法

<?php
$arg = [
  'post_type'    => 'product',
  'meta_key'     => 'pickup',
  'meta_value'   => 'on',
  'meta_compare' => '=', // "=" はデフォルトなので省略可
];
$the_query = new WP_Query($arg);

meta_query で指定する場合

<?php
$arg = [
  'post_type'  => 'product',
  'meta_query' => [
    [
      'key'     => 'pickup',
      'value'   => 'on',
      'compare' => '=',  // "=" はデフォルトなので省略可
    ],
  ],
];
$the_query = new WP_Query($arg);

複数のカスタムフィールドを条件にするとき

カスタムフィールド pickuponで、カスタムフィールドsale_end_atの日付が今日より大きい product (post_type)を取得した場合。
複数のカスタムフィールドを条件にしたい場合はmeta_queryの配列に条件を追加すればOK

<?php
$arg = [
  'post_type'  => 'product',
  'meta_query' => [
    [
      'key'     => 'pickup',
      'value'   => 'on',
    ],
    [
      'key'     => 'sale_end_at',
      'value'   => date( "Y-m-d" ),
      'compare' => '>',
    ],
  ],
];
$the_query = new WP_Query($arg);

複数のカスタムフィールドの値を AND で取得することができます。

複数のカスタムフィールドの条件をORで取得したいとき

meta_queryのカスタムフィールドの条件がある階層にrelationで指定することができます。(relationの指定がないとANDになります。)

カスタムフィールドsale_end_atの日付が今日より大きい または sale_end_atが指定されていない(未登録) で取得したい場合。

<?php
$arg = [
  'post_type'  => 'product',
  'meta_query' => [
    'relation' => 'OR',
    [
      'key'     => 'sale_end_at',
      'value'   => date( "Y-m-d" ),
      'compare' => '>',
    ],
    [
      'key'     => 'sale_end_at',
      'compare' => 'NOT EXISTS',
    ],
  ],
];
$the_query = new WP_Query($arg);

複数のカスタムフィールドでの複雑な条件での取得

カスタムフィールド pickuponで、
カスタムフィールドsale_end_atの日付が今日より大きい または sale_end_atが指定されていない(未登録) で取得したいような場合... 日本語で書くとややこしい...

pickup = "on" && ( sale_end_at > TODAY || NOT EXISTS (sale_end_at)  )

こんな感じの条件にしたいイメージです。

どうやら、meta_queryの配列内に配列を入れ子にして条件を作成することができるようです。

<?php
$arg = [
  'post_type'  => 'product',
  'meta_query' => [
    'relation' => 'AND',
    [
      'key'     => 'pickup',
      'value'   => 'on',
      'compare' => '=',
    ],
    [
      'relation' => 'OR',
      [
        'key'     => 'sale_end_at',
        'value'   => date( "Y-m-d" ),
        'compare' => '>',
      ],
      [
        'key'     => 'sale_end_at',
        'compare' => 'NOT EXISTS',
      ],
    ],
  ],
];
$the_query = new WP_Query($arg);

 
WP_Query すごい!!

ただ、カスタムフィールドの値でORDER_BYの条件にしたい時はmeta_keyに条件にするカスタムフィールドを指定しなければならないっぽいので、上記の条件でsale_end_atで並び替えようとするとsale_end_atが存在しない(NOT EXISTS)な投稿は取得されなくなってしまうのでORDER_BYと併用する場合は注意が必要です。(存在しない値のものがあるとどう並び替えるねん!ってなるから当然といえば当然ですが...

<?php
$arg = [
  'post_type'  => 'product',
  'meta_query' => [
    'relation' => 'AND',
    [
      'key'     => 'pickup',
      'value'   => 'on',
      'compare' => '=',
    ],
    [
      'relation' => 'OR',
      [
        'key'     => 'sale_end_at',
        'value'   => date( "Y-m-d" ),
        'compare' => '>',
      ],
      [
        'key'     => 'sale_end_at',
        'compare' => 'NOT EXISTS',
      ],
    ],
  ],
  'meta_key' => 'sale_end_at',
  'orderby'  => [
    'date'       => 'DESC',
    'meta_value' => 'ASC',
  ],
];
$the_query = new WP_Query($arg);

👆sale_end_atNOT EXISTS の投稿は取得されない。
並び替えが必要なら素直に2回 WP_Queryを発行するか、WP_Queryで取得した値をループさせて手動で並び替えを行うかで対処することになります。(DB問い合わせが少ないほうが良さそうかも!?

改めてWP_Queryって色々できるんだなーと知りました。


イタリア商事 ホットサンドメーカー ニュー・バウルー ダブル BW02

イタリア商事 ホットサンドメーカー ニュー・バウルー ダブル BW02


👆これ買ったので早く使いに行きたい。