今回のエントリー作成にあたっては、WordPressの日本語フォーラムで活発なフォローをされている@kzxtremeさんのエントリー
WordPress のURLクエリストリングにカスタムフィールドを指定して絞り込み検索する
http://wpxtreme.jp/search-with-custom-fields-in-url-query-parameters
がたいへん参考になりました。まずは@kzxtremeさんに大感謝です 😀
私は何をしたかったのか
カスタム投稿の記事を、カスタムフィールドの値で絞り込み検索したかったのです。具体的にいうと、会議室・レンタルスペースのガイド的なサイトを
- 会議室・レンタルスペースの個別ページ……カスタム投稿「facilities」で登録
- 駐車場の有無……カスタムフィールドで定義。キーは「parking」、値は「あり(無料)」「あり(有料)」「なし」の3とおり
というかたちで作っていて、「facilities」の全投稿の中から駐車場がある施設、つまり、値に「あり(無料)」「あり(有料)」のいずれかを持つものを抽出したかったんですね。
最初にやったこと
@kzxtremeさんのエントリーにあるサンプルコード(「よりクールな方法」の方)をもとに functions.php に
global $my_public_query_vars; $my_public_query_vars = array( 'parking' ); add_filter( 'query_vars', 'my_query_vars' ); function my_query_vars( $public_query_vars ) { global $my_public_query_vars; return array_merge( $public_query_vars, $my_public_query_vars ); } add_action( 'pre_get_posts', 'my_pre_get_posts' ); function my_pre_get_posts( $query ) { if ( ! is_admin() && is_post_type_archive( 'facilities' ) /* && 'staff' == $query->get( 'post_type' ) */ ) { $meta_query = array(); global $my_public_query_vars; foreach ( $my_public_query_vars as $key ) { if ( $val = $query->get( $key ) ) { $meta_query[] = array( 'key' => $key, 'value' => $val, ); } } if ( ! empty( $meta_query ) ) { $query->set( 'meta_query', $meta_query ); } } }
と書きました。ざっくり簡単に補足すると
- 前半……URLクエリストリングに「parking」を使えるように設定
- 後半……「facilities」のアーカイブページが表示されているとき、カスタムフィールド「parking」の値を抽出、値に応じてループのクエリを書き換える
という流れになってます。
検索フォームと結果表示のページをどう作る?
そですね。作らないといけません。
検索フォームはこんなかたちで書きました。
<form method="get" id="searchform-parking" action="<?php echo esc_url( home_url( '/facilities/' ) ); ?>"> <input type="checkbox" class="field" id="parking" name="parking" value="あり"/>駐車場あり<br /> <input type="submit" class="submit" name="submit" id="searchsubmit-parking" value="検索" /> </form>
1行目の home_url( ‘/facilities/’ ) が functions.php の内容と関係する記述です。こう書くことで http://www.example.com/facilities/?parking=あり というURLになったとき、駐車場がある施設が抽出されることになるわけです。
もっとも、これだと archive.php が検索結果の表示に使われるので、デザインのカスタマイズをしたい場合はテンプレート階層を活用して archive-facilities.php を新規作成のうえごにょごにょする必要があります。
ところがこれだと該当数ゼロになる
ええ、ゼロになってしまいました。
カスタムフィールドの値は「あり(無料)」「あり(有料)」「なし」の3とおり。ところが、検索フォームでは「あり」という値で呼び出しをかけています。カスタムフィールドにない値で斜め上行く検索をして、該当数ゼロになってる……つまり、この方法は「完全一致検索」を狙わないと使えないやりかただったのです。
魔法の呪文 ‘compare’ => ‘LIKE’
そんな状況を先読みしてたかどうかはわかりませんが、WordPressの中の方たちはすごいですね。部分一致検索ができる呪文を用意してくれてました。それが ‘compare’ => ‘LIKE’ というフレーズです。
Codexの英語版にこんな解説があります。@bren_bossさんありがとう。
- meta_query (array) – Custom field parameters (available with Version 3.1).
- key (string) – Custom field key.
- value (string|array) – Custom field value (Note: Array support is limited to a compare value of ‘IN’, ‘NOT IN’, ‘BETWEEN’, or ‘NOT BETWEEN’)
- compare (string) – Operator to test. Possible values are ‘=’, ‘!=’, ‘>’, ‘>=’, ‘<‘, ‘<=’, ‘LIKE’, ‘NOT LIKE’, ‘IN’, ‘NOT IN’, ‘BETWEEN’, ‘NOT BETWEEN’. Default value is ‘=’.
- type (string) – Custom field type. Possible values are ‘NUMERIC’, ‘BINARY’, ‘CHAR’, ‘DATE’, ‘DATETIME’, ‘DECIMAL’, ‘SIGNED’, ‘TIME’, ‘UNSIGNED’. Default value is ‘CHAR’.
「compare」の欄に注目ですね。デフォルトだと = (完全一致)でカスタムフィールドの値を検索するところ、SQLのLIKE演算子よろしく部分一致の設定ができるのです。部分一致を実現するには先ほどの functions.php にて
- 'value' => $val, + 'value' => $val, + 'compare' => 'LIKE'
と書けばオッケイ。これでやっと、「あり(無料)」「あり(有料)」両方の記事を引っぱってくることができるようになりました。
ほかにもSQLにならった演算子があったり、データ型を指定できたりもするので、興味がある方はいろいろ試されてはいかがでしょうか。
コメントを残す