はじめに
WordPressでタイトル・内容・カスタムフィールドをOR条件で検索したいことがあったんです。
get_posts
でもWP_Query
でもいいんですけど、パラメーターで、
- タイトル・内容は「s」
- カスタムフィールドは「meta_query」
を設定すればいいんですけど、これだとAND条件でつながるんですよね。(普通はこれでいい)
今回は、上記をOR条件でつなぎたかったので、それをどうするかというお話。
パラメーター「s」のSQL
AND (((wp_posts.post_title LIKE '%テスト%')
OR (wp_posts.post_excerpt LIKE '%テスト%')
OR (wp_posts.post_content LIKE '%テスト%')))
パラメーター「meta_query」のSQL
AND ( ( ( wp_postmeta.meta_key = 'prefecture' AND wp_postmeta.meta_value LIKE '%テスト%' )
OR ( wp_postmeta.meta_key = 'area_detail' AND wp_postmeta.meta_value LIKE '%テスト%' )
OR ( wp_postmeta.meta_key = 'genre' AND wp_postmeta.meta_value LIKE '%テスト%' )
OR ( wp_postmeta.meta_key = 'practice_time' AND wp_postmeta.meta_value LIKE '%テスト%' )
OR ( wp_postmeta.meta_key = 'experience' AND wp_postmeta.meta_value LIKE '%テスト%' ) ) )
この2つをORでつなげばOK
やり方
WordPressには、標準で出力されるSQLのwhere句を追加できるフィルターがあるらしい
posts_where
フィルター
ちなみに、どのページのときに使うかなどを設定しないと、全部のSQLにフィルターかかるので注意!!
このSQLでタイトル・内容・カスタムフィールドをすべてOR条件でくっつけます。
add_filter('posts_where', 'add_my_query');
function add_my_query($where) {
//テストの固定ページのときだけ
if(is_page('test')) {
isset($_GET['freeword']) ? $freeword = $_GET['freeword'] : $freeword = '';
if($freeword) {
$where .= <<<EOM
AND (wp_posts.post_title LIKE '%{$freeword}%'
OR wp_posts.post_content LIKE '%{$freeword}%'
OR ( wp_postmeta2.meta_key = 'prefecture' AND wp_postmeta2.meta_value LIKE '%{$freeword}%' )
OR ( wp_postmeta2.meta_key = 'area_detail' AND wp_postmeta2.meta_value LIKE '%{$freeword}%' )
OR ( wp_postmeta2.meta_key = 'genre' AND wp_postmeta2.meta_value LIKE '%{$freeword}%' )
)
EOM;
}
}
return $where;
}
wp_postmeta2
というのはwp_postmeta
のエイリアスです。名前はなんでもいいんだけど。
条件にmeta_query
が入っている場合は、名前が重複して怒られたり、逆にmeta_query
が入っていないと、テーブルないやんって怒られます。
だから、joinのときもフィルターを使って、wp_postmeta
テーブルをくっつけてあげます。
posts_join
フィルター
add_filter('posts_join', 'add_my_join');
function add_my_join($join) {
//テストの固定ページのときだけ
if(is_page('test')) {
$join .= 'INNER JOIN wp_postmeta as wp_postmeta2 ON ( wp_posts.ID = wp_postmeta2.post_id )';
}
return $join;
}
まとめ
普通に検索ページなどで使いたいのであれば、それようのプラグインもあったような気がします。
余談
meta_queryパラメーター
WP_Query
やget_posts
で、meta_query
のパラメーター使うときにはまるのが、「meta_query はクエリがひとつだけでも入れ子の配列を指定しなければなりません。」というところかな。
自分もはまるし、他の人もはまってます。
まぁ、relationがAND
かOR
を設定できると知っていれば、はまることはなさそうですが...
WordPressのページネーション
基本、get_posts
を使いますが、アーカイブとかタクソノミーページでないのに、記事一覧を取得してページャーを作りたいときは、WP_Query
を使用します。
なんかプラグイン使ったり、長々と独自関数書いている記事もよく見かけますが、
関数リファレンス/paginate linksの「カスタムクエリを使用した例」をコピペすれば十分なんじゃないかと思ってます。
アーカイブページなどの場合は、ほぼpaginate_links()
で事足りますね。