タグ:検索
WordPressの検索機能をカスタマイズ
WordPressの検索の欠点として
- カスタムフィールドが対象外
- カテゴリー・タグ(タクソノミー)が対象外
というものがあります。
最近は内容フィールドは使用せず、カスタムフィールドに中身を入れるといった場合もあるので、これでは大変不便です。
ということで、検索機能をカスタマイズし、これらからも引っ張ってくるようにします。(ついでに抜粋からも)
なお、検索処理のカスタマイズは「pre_get_posts」をフックした関数にて行います。
pre_get_postsについては、こちらをご覧ください(query_postsを捨てよ、pre_get_postsを使おう【追記あり】【報告あり】)。
functions.phpに下記を追加します。
※pre_get_postsをフックした関数がすでに存在していている場合は、うまく編集してください。
function my_pre_get_posts($query) { //管理画面には適応しない if ( is_admin() || ! $query->is_main_query() ) return; //検索画面の場合 if($query->is_search()){ global $wpdb; $keywords = get_search_query(); if($keywords){ $keywords = str_replace(" ", " ", $keywords); $keyword_array = explode(" ", $keywords); $post_ids = array(); $post_ids_exists = array(); foreach($keyword_array as $keyword){ $post_ids_meta = array(); //カスタムフィールド $post_ids_post = array(); //タイトル・内容 $post_ids_term = array(); //カテゴリー if($keyword){ $keyword = '%' . like_escape( $keyword ) . '%'; //カスタムフィールド内を検索 $post_ids_meta = $wpdb->get_col( $wpdb->prepare( " SELECT DISTINCT post_id FROM {$wpdb->postmeta} WHERE meta_value LIKE '%s' ", $keyword ) ); //タイトルと内容・抜粋から検索 $post_ids_post = $wpdb->get_col( $wpdb->prepare( " SELECT DISTINCT ID FROM {$wpdb->posts} WHERE post_title LIKE '%s' OR post_content LIKE '%s' OR post_excerpt LIKE '%s' ", $keyword, $keyword, $keyword ) ); //カテゴリー名から検索 $term_ids = $wpdb->get_col( $wpdb->prepare( " SELECT DISTINCT term_id FROM {$wpdb->terms} WHERE name LIKE '%s' ", $keyword) ); //ヒットしたカテゴリーが所属する投稿 if($term_ids){ $term_id = implode(",", $term_ids); $post_ids_term = $wpdb->get_col( $wpdb->prepare( " SELECT DISTINCT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN (%s) ", $term_id) ); } //各処理で取得した投稿IDをマージする。 $post_ids_tmp = array(); $post_ids_tmp = array_merge($post_ids_meta, $post_ids_post, $post_ids_term); //重複している投稿IDのみ抜き出す(AND検索のため) if($post_ids_tmp){ //検索ワード1つ目の場合、$post_ids_existsのキーに投稿IDを入れていく(内容はtrue) if(empty($post_ids_exists)){ foreach($post_ids_tmp as $post_id){ $post_ids_exists[$post_id] = 1; } } //検索ワード2つ目以降の場合 else{ //○つ目の投稿IDを$post_ids_exists_tmpキーに入れていく(内容はtrue) $post_ids_exists_tmp = array(); foreach($post_ids_tmp as $post_id){ $post_ids_exists_tmp[$post_id] = 1; } //1つ目の$post_ids_existsと、○つ目の$post_ids_exists_tmpとを比較し、存在しない場合はunsetする。 foreach($post_ids_exists as $post_id => $value){ if($post_ids_exists_tmp[$post_id] != 1){ unset($post_ids_exists[$post_id]); } } } } } } //まとめた$post_ids_existsのキー(投稿ID)を、内容に移す if($post_ids_exists){ foreach($post_ids_exists as $post_id => $value){ $post_ids[] = $post_id; } } if($post_ids){ $query->set('post__in', $post_ids); }else{ $query->set('post__in', array(0)); } }else{ $query->set('post__in', array(0)); } $query->set('s', ''); //本来の検索は邪魔になるので削除しておく } } add_action( 'pre_get_posts', 'my_pre_get_posts' );
最後に、
$query->set('s', '');
を行っているため、検索結果ページで、$sやget_query_var('s')から検索ワードを取得できなくなっています。
そのため、search.phpのget_header()の前に
$wp_query->query_vars["s"] = $wp_query->query["s"];
を追記してください。
これで$sやget_query_var('s')を使って検索ワードを取得できるようになります。
しかし結構ごつい処理をしてるので重くなりそうな気も・・・大丈夫かな。
参考サイト
nandani | 2014年12月17日 | コメント(2) | トラックバック(0) | CMS関連