[WordPress] pre_get_postsでカスタムフィールドの値を利用した表示の制御

pre_get_posts() を使うと表示の制御ができる。
根本はWP_Queryなので、ここにまとめたカスタムフィールドのクエリはget_postsとかでも使うことができる。
pre_get_postsの基本的な使い方はググれば色々でてくるんでそちら見てもらうとして、この記事はカスタムフィールドの値を絞り込みに利用するケースについてまとめたものです。

雛形

管理画面とメインクエリでない場合は飛ばす、これは必須。

add_action( 'pre_get_posts', function($query) {
  if ( is_admin() || ! $query->is_main_query() ){
    return;
  }
  // ここに追加していく
});

meta_queryやtax_queryはMySQLの構文そのままなので、行き詰まったらWordPressよりMySQLのドキュメント見る方が良い。

条件が複雑になりすぎると動作が遅くなることがあるのでやりすぎに注意。

比較

valueで指定した値とカスタムフィールドの値を比較できる。デフォルトは =

演算子 意味
= a と b は等しい
!= a と b は等しくない
< a は b よりも小さい
<= a は b よりも小さいか等しい
> a は b よりも大きい
>= a は b よりも大きいか等しい

カスタムフィールドの値は文字列として保存されるので、 <=><>は利用できない。

例:カスタムフィールド ‘cat’ が ‘アビシニアン’ ではない投稿

$query->set( 'meta_query',
  array(
    'key' => 'cat',
    'value' => 'アビシニアン',
    'compare' => '!='
  )
);

例:カスタムフィールド ‘event_date’ が 今日以降 の投稿

$query->set( 'meta_query',
  array(
    'key' => 'event_date',
    'value' => date( "Ymd" ),
    'compare' => '>'
  )
);

あいまい

LIKENOT LIKE が利用できる。

文字 意味
% %hoge →後方一致
hoge% →前方一致
%hoge% →中間一致
_ 任意の1文字

例:カスタムフィールド ‘area_name’ に ‘府’ を含む投稿

$query->set( 'meta_query',
  array(
    'key' => 'area_name',
    'value' => '%府%',
    'compare' => 'LIKE'
  )
);

例:カスタムフィールド ‘device’ が iPhone4〜X の投稿

$query->set( 'meta_query',
  array(
    'key' => 'device',
    'value' => 'iPhone_',
    'compare' => 'LIKE'
  )
);

リスト比較

INNOT IN が利用できる。
valueで比較対象になる配列を指定しなければならない。

例:カスタムフィールド ‘cat_color’ が 三毛、サバトラ、茶トラ のいずれかに該当する投稿

$query->set( 'meta_query',
  array(
    'key' => 'cat_color',
    'value' => array('三毛', 'サバトラ', '茶トラ'),
    'compare' => 'IN'
  )
);

範囲

BETWEENNOT BETWEEN が利用できる。
typeでdateまたはdatetimeを指定すると日付の比較ができるが、比較するカスタムフィールドが YYYY-MM-DD 形式で保存されている必要がある。

例:カスタムフィールド ‘event_date’ が 2018/08/01 〜 2018/08/31 に該当する投稿

$query->set( 'meta_query',
  array(
    'key' => 'event_date',
    'value' => array('2018-08-01', '2018-08-31'),
    'type' => 'date',
    'compare' => 'BETWEEN'
  )
);

例:カスタムフィールド ‘price’ が 1000 〜 5000 に該当する投稿

$query->set( 'meta_query',
  array(
    'key' => 'price',
    'value' => array(1000, 5000),
    'type' => 'numeric',
    'compare' => 'BETWEEN'
  )
);

正規表現

REGEXPNOT REGEXPが利用できる。

例:カスタムフィールド ‘domain’ が アルファベット、数字、ピリオド で構成された値である投稿

$query->set( 'meta_query',
  array(
    'key' => 'domain',
    'value' => '[[:alnum:][:alpha:][.period.]]+',
    'compare' => 'REGEXP'
  )
);

複数の条件

条件が複数ある場合、 relationで AND または OR を 指定する。

例:カスタムフィールド ‘cat’ が ‘日本猫’ かつ ‘cat_color’ が 三毛、サバトラ、茶トラ のいずれかに該当する投稿

$query->set( 'meta_query',
 array(
    'relation' => 'AND',
    array(
      'key' => 'cat',
      'value' => '日本猫',
      'compare' => '='
    ),
    array(
      'key' => 'cat_color',
      'value' => array('三毛', 'サバトラ', '茶トラ'),
      'compare' => 'IN'
    )
 )
);

指定した値に該当しない条件指定

カスタムフィールドを途中で新設した場合、カスタムフィールドを設定した時点より前に保存された投稿にはカスタムフィールドのカラムが存在しない。
値の比較だけだとそれらの投稿がtrueにならないのでNOT EXISTSも使う。

例:カスタムフィールド ‘display’ が ‘false’ 以外と、カスタムフィールド未設定の投稿

$query->set( 'meta_query',
 array(
    'relation' => 'OR',
    array(
      'key' => 'display',
      'value' => 'false',
      'compare' => '!='
    ),
    array(
      'key' => 'display',
      'compare' => 'NOT EXISTS'
    )
 )
);

条件のネスト

ANDとORを同時に使いたい、みたいな時は入れ子にする。

$query->set( 'meta_query',
 array(
    'relation' => 'AND',
    array(
      'key' => 'cat',
      'value' => 'アビシニアン',
      'compare' => '!='
    ),
    array(
      'key' => 'cat_color',
      'value' => array('三毛', 'サバトラ', '茶トラ'),
      'compare' => 'IN'
    ),
    array(
      'relation' => 'OR',
      array(
        'key' => 'display',
        'value' => 'false',
        'compare' => '!='
      ),
      array(
        'key' => 'display',
        'compare' => 'NOT EXISTS'
       )
    )
 )
);

カスタムフィールドの値による並び替え

orderbyの指定で meta_valuemeta_value_num を設定すると、
meta_keyで指定したカスタムフィールドの値で並び替えができる。
文字列比較の場合はmeta_value、数値比較の場合はmeta_value_numを使う。

$query->set('meta_key', 'custom_order');
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');

orderbyは配列で複数指定できる。

$query->set('meta_key', 'custom_order');
$query->set('orderby', array( 'meta_value_num' => 'DESC', 'title' => 'ASC' ));

meta_keyを複数指定したい場合は、meta_queryでクエリを設定するとき配列に名前をつける。

$query->set( 'meta_query',
  array(
    'relation' => 'AND',
    'price' => array(
      'key' => 'price',
      'value' => array(1000, 5000),
      'type' => 'numeric',
      'compare' => 'BETWEEN'
    ),
    'event_date' => array(
      'key' => 'event_date',
      'value' => array('2018-08-01', '2018-08-31'),
      'type' => 'date',
      'compare' => 'BETWEEN'
    )
  )
);
$query->set('orderby', array( 'event_date' => 'DESC', 'price' => 'ASC' ));

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください