WordPressのデフォルトの検索をカスタマイズする
Posted by admin at 8:17 日時 2011/06/29
公式フォーラムに上がってた質問から、WordPressのデフォルトの検索をカスタマイズする方法を調べてみました。WordPressにはSQLクエリをカスタマイズするためのフィルターフックが用意されているので、それを使います。
たとえば、検索対象にスラッグ(post_name)を含めるというカスタマイズを考えてみます。何もカスタマイズしていない状態で「hello-world」(インストール時に作られるHello World!という投稿のスラッグ)で検索した場合、このようなクエリが発行されます。
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND (((wp_posts.post_title LIKE ‘%hello-world%’) OR (wp_posts.post_content LIKE ‘%hello-world%’))) AND wp_posts.post_type IN (‘post’, ‘page’, ‘attachment’) AND (wp_posts.post_status = ‘publish’ OR wp_posts.post_author = 1 AND wp_posts.post_status = ‘private’) ORDER BY wp_posts.post_date DESC LIMIT 0, 10
デフォルトでは、投稿のタイトル(wp_posts.post_type)と本文(wp_posts.post_content)のみが検索対象になっているのが分かります。このクエリを改造して、スラッグ(wp_posts.post_name)も検索対象に追加します。そのコードが以下です。
function post_name_search_where( $where, $obj ) { global $wpdb; if ( $obj->is_search ) { $where = preg_replace( "/\(\s*$wpdb->posts\.post_title\s+LIKE\s*(\'[^\']+\')\s*\)/", "($wpdb->posts.post_title LIKE $1) OR ($wpdb->posts.post_name LIKE $1)", $where ); } return $where; } add_filter( 'posts_where', 'post_name_search_where', 10, 2 );
正規表現で(wp_posts.post_title LIKE ‘%hello-world%’)という部分を探してきて、(wp_posts.post_title LIKE ‘%hello-world%’) OR (wp_posts.post_name LIKE ‘%hello-world%’)に置き換えています。if文でこの置換は検索時にしか有効にならないようにしています。
このコードはwp_postsテーブルの中で検索対象を追加する場合で、カスタムフィールドなど、別のテーブルを検索対象にする場合はposts_joinフィルターも併用する必要があります。詳しくはCodexのCustom Queriesのページを参考にしてください。
この記事を作成するに当たって、 @jim0912 さんに色々情報をいただきました。ありがとうございます。