WordPressにはウィジェットとして、下のような検索フォームが追加できるようになってるじゃないですか。
設置したら、こんな感じで表示されます。(Twenty Twelveテーマを使った場合)
それで、便利なんですけど、そのままだと検索結果に固定ページも含まれてしまいますね。私のこのブログで言うと、aboutページやプラグイン解説ページなどがそうです。「・・・検索結果にページは表示しなくてもいいなぁ~」と思われた方は、検索結果で固定ページの表示を除外しましょう。
検索結果で「投稿のみ」表示させる
Codexの「Plugin API/Action Reference/pre get posts」に、
サンプルコードが掲載されています。下のコードを「functions.php」に追記しましょう。
function SearchFilter($query) { if ($query->is_search) { //検索結果ページが表示されている場合 $query->set('post_type', 'post'); //投稿タイプが投稿のみ } return $query; } add_action('pre_get_posts','SearchFilter'); //アクションフック
やっていること
WordPressに造詣の深いというか、マニアというか、そんな方々の中では何かと話題っぽい「pre_get_posts」を使ってやってますね。検索結果ページが表示されている時は、投稿タイプが投稿のものだけ表示させようってことですね。
そのままですね。
これでOK!と行きたいところですが、コード変更のアドバイスをいただきました
上に紹介したコードを使うと、いくつかの問題があることを理解しました。それを回避するための4つのアドバイスを、@jim0912さんから教えていただきました。(アイコンで、どなたか一発でわかってしまいますねw)
具体的にどういう問題があるのか。以下を読んでどこがまずいのか。まずいところをどうやって解決しているのか、見ましょう。
1.WordPressの管理画面の「固定ページを検索」のところが「問題」
今までこれ、使ったことがなかったんで知らなかったんですがね・・・下の画像をご覧ください。WordPressの管理画面に「固定ページを検索」って箇所があります。
入力欄に「about」と入れます。
すると、検索結果が下のようになります。
固定ページを検索したいのに、投稿が表示されてる。これは問題
というわけでして、このままでは管理画面上の表示結果にも影響が出ますね。そこで。いただいだアドバイスは以下です。
pre_get_posts のクエリーは、管理画面の記事一覧の表示などにも適用されるので、
判別条件に「管理画面でなければ」( ! is_admin())を加えた方がよいです。
例えば、ご呈示のコードですと、管理画面の固定ページ一覧で、固定ページの検索ができなくなってしまいます。
なるほど・・・「!is_admin()」を追記することで、これは解消できるようです。
2.「pre_get_posts」フックによる影響が広範囲だという「問題」
頂いたアドバイスが的確ですので、そのまま掲載しますと・・・
pre_get_posts フックは、メインクエリー以外にも、ナビゲーションメニューの表示や、
get_posts などによる記事抽出の際にも適用されます。
検索結果のみなど、メインクエリーにのみ影響を及ぼしたい場合は、is_main_query() を判別条件として、
影響範囲を限定させた方が意図しない不具合を制限できます。
http://codex.wordpress.org/Function_Reference/is_main_query
なるほど・・・「pre_get_posts」を使うところを、明示的に指定することで回避できますね。今回は、検索結果だけ表示を変更できればよいです。なので、メインクエリーにあたる部分ですね。「is_main_query()」を追記することが望ましい、ということですね。
3.「$query->is_search()」を使ったほうが、後々のことを考えると「よい」
これも、頂いたアドバイスをそのまま掲載いたしますと・・・
$query->is_search でも結果としては同一となりますが、
$query->is_search は、オブジェクトのメンバー変数の参照となります。
$query->is_search() としてメソッドを利用した方が、内部の実装が変更された際にも影響を受けにくい
(おそらく後方互換となりやすい)ため、メソッドを利用した方が望ましいと思われます。
これはとてもよくわかりました。なので、「$query->is_search()」に書き換えましょう。
4.結果を返すコード「return」は「要らない」
えっと・・ここも頂いたアドバイスを掲載しますと・・・・
pre_get_posts フックは、
do_action_ref_array(‘pre_get_posts’, array(&$this));
となっており、WP_Queryのオブジェクト自体を参照で受け取ります。
このため、フック内で set すれば、その時点で適用されるため、return する必要は一切ありません。
「pre_get_postsフックは、do_action_ref_array(‘pre_get_posts’, array(&$this));・・・」
のところを実際に見たかったので、query.php in tags/3.5.1/wp-includes – WordPress Trac を探すと、「pre_get_posts」に関するコード部分を確認しました。以下のようにありますが、このことかな・・・
/** 1908 * Retrieve the posts based on query variables. 1909 * 1910 * There are a few filters and actions that can be used to modify the post 1911 * database query. 1912 * 1913 * @since 1.5.0 1914 * @access public 1915 * @uses do_action_ref_array() Calls 'pre_get_posts' hook before retrieving posts. 1916 * 1917 * @return array List of posts. 1918 */ 1919 function get_posts() { 1920 global $wpdb, $user_ID, $_wp_using_ext_object_cache; 1921 1922 $this->parse_query(); 1923 1924 do_action_ref_array('pre_get_posts', array(&$this)); 1925 1926 // Shorthand. 1927 $q = &$this->query_vars; 1928 1929 // Fill again in case pre_get_posts unset some vars. 1930 $q = $this->fill_query_vars($q); 1931 1932 // Parse meta query 1933 $this->meta_query = new WP_Meta_Query(); 1934 $this->meta_query->parse_query_vars( $q ); 1935 1936 // Set a flag if a pre_get_posts hook changed the query vars. 1937 $hash = md5( serialize( $this->query_vars ) ); 1938 if ( $hash != $this->query_vars_hash ) { 1939 $this->query_vars_changed = true; 1940 $this->query_vars_hash = $hash; 1941 } 1942 unset($hash);
コードについては現状ではここまでの理解ですが、アドバイスの内容は理解できます。「return $query;」のコードは削除しましょう。
以上を踏まえて、先ほど書いたCodexのコードを下のように変更しましょう。
アドバイスの内容を理解したところで、このコードを使おう
ここまでいただいたアドバイスを元に、下記のコードに変更しました。
function SearchFilter($query) { if ( !is_admin() && $query->is_main_query() && $query->is_search() ) { $query->set( 'post_type', 'post' ); } } add_action( 'pre_get_posts','SearchFilter' );
これでOK。
実行結果をサンプルとして、以下に掲載しておきますね。
サンプル
私のブログで「about」とフォームに入力しました。
【使用前:検索結果に「aboutページ」が入っている】
【使用後:aboutページが除外されている】
いいですねぇ~。
これがやりたかった!
続いて、わかりやすいところでWordPressの管理画面の固定ページ一覧の検索結果を見ましょう。
入力欄に「about」と入れます。
検索結果に、ちゃんと「Aboutページ」が表示されていますね。
閲覧画面側も意図したように、固定ページを除外して検索結果を表示していますし、管理画面側も本来の動作を損なわず、検索結果を表示してますね。どちらもいい感じです。
まとめ
ところで私は、この検索フォームってよく使います。特に自分のブログで、「昔あのことについて書いた気がするな~。検索しよう」と思ってよく使います。その時、いつも固定ページまで検索結果に表示されてました。
今回書いた方法は、わりと少しのカスタマイズで済みます。細かいことですけども、是非とも。
また、コードについてのアドバイスをいただきました@jim0912さんにはとても感謝しています。ありがとうございました!
このページを共有する