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さんにはとても感謝しています。ありがとうございました!
こちらの記事を参考にサイト内検索から固定ページの除外をしたいのですが、
私のサイトでは アドバイスの内容を理解したところで、このコードを使おうの コードでは非表示になりませんでした。
固定ページも少なく管理画面から固定ページを検索することもほぼないので一番上のタグを使用させていただきます。こちらの場合は表示になりました。これはテーマの問題なのでしょうか?
2013/06/05 15:58:36
ツイート
シェア
どうなんでしょうかねぇ。テーマは、どのテーマをお使いでしょうか。
お好みでカスタマイズされているかもしれないので、原因を解消できるかどうかはわからないところですが、もし差支えなければ教えて頂けますでしょうか。
2013/06/05 17:35:38
ツイート
シェア