【WordPress】検索条件を残したまま複数のカスタムタクソノミー(ターム)で検索

WordPress

カスタムタクソノミーを複数設定しているサイトで、絞り込み検索を行いました。

最初に参考にさせていただいたのはこちらのサイト。

絞り込み検索をプラグインを使わずに実装[WordPress]
WordPressで絞り込み検索をプラグインを使用せずに実装する方法を紹介します。「Custom Fields Search」はサポート終わってる?「FE Advanced Search」はちょっと高い?大丈夫です!自分で実装してみましょう...

「プラグインを使わずに」というのも重要です。

こちらのサイトを参考に作っていたのですが、どうも検索結果のページネーションがうまく動作しませんでした。原因は query_posts を使っていることだったようで、調べてみるとこの関数を使うことは今は非推奨のようです。(2018年1月現在)

調べているうちにこういうサイトに出会いました。

query_postsを捨てよ、pre_get_postsを使おう【追記あり】【報告あり】

タイトルで「query_postsを捨てよ」といきなりバッサリ。

代わりに pre_get_posts という関数をおすすめされているのでこちらも調べてみましたが、WordPressでページが読み込まれる前に、メインクエリをカスタマイズしよう、ということのようです。

これまではメインクエリやらサブクエリやらの認識も曖昧で、特別に意識したことはなかったのですが、今回非常に勉強になりました。

メインクエリとサブクエリの違い等も含め pre_get_posts についてとてもわかり易くしてくださっているスライドがこちらにありました。99ページありますがとってもスラスラ見れます。

WordPressでページ送りが動かないのはどう考えてもquery_postsが悪い!【pre_get_posts、WordPressループまとめ】

というわけで、私も pre_get_posts を利用して検索結果を作ってやろう!とあれやこれやしてたんですが、どうもうまくいかない…。テンプレートファイルが必要なのかも…?とわざわざ作ってもダメで…。検索がうまくいかないどころか常に検索結果が0(ゼロ)の状態でした。

本当に悩んであれこれやってたんですが、原因というかなんでうまく行かなかったかというのは意外なところにありました。

検索結果を表示するのに pre_get_posts は必要なかったのです…。

query_posts から pre_get_posts に移行するので絞込の処理を何かしなくちゃ!と思い込んでたんですね。

WordPressではタクソノミーだろうがなんだろうが検索フォームをきちんと作っていれば適切な検索結果を出してくれるみたいです。素晴らしい。。

随分遠回りをしましたが、私が作った検索フォームはこちら。都合により関数になってます。

<?php
function my_searchform() {
?>	
	<form class="searchform" method="get" action="<?php bloginfo( 'url' ); ?>">
		<p>絞込検索</p>
		<div class="searchbox">
			<ul class="cf">
<?php
	$tax_arr = get_my_taxonomies();
	foreach ( $tax_arr as $taxonomy ) {
		$taxonomy_name = get_taxonomy( $taxonomy ) -> label;
?>		
				<li class="<?php echo $taxonomy; ?>">
					<p><?php echo $taxonomy_name; ?></p>
					<div>
<?php
		$serach = $_GET[$taxonomy];
		$terms = get_terms( $taxonomy, 'orderby=count&hide_empty=1&order=DESC' );
		foreach ( $terms as $term ){
			if( in_array( $term -> slug, $serach ) ){
				$checked = ' checked';
			}else{
				$checked = '';
			}
?>
						<label for="check_<?php echo $taxonomy; ?>_<?php echo $term -> slug; ?>">
							<input id="check_<?php echo $taxonomy; ?>_<?php echo $term -> slug; ?>" type="checkbox" name="<?php echo $taxonomy; ?>[]" value="<?php echo $term -> slug; ?>"<?php echo $checked; ?>><?php echo $term -> name; ?>
						</label>
<?php
		}
?>
					</div>
				</li>
<?php
	}
	?>
				<li class="freeword">
					<p>フリーワード</p>
					<div>
						<input type="text" value="<?php echo get_search_query(); ?>" name="s" id="s" />
					</div>
				</li>
			</ul>
			<div class="button_box">
				<input type="submit" class="btn_search" id="submit" value="検索">
				<input type="button" class="btn_reset" value="条件クリア">
				<input type="button" class="btn_all" onclick="location.href='(サイトURL)/?s='" value="条件をクリアして全件表示">
			</div>
			</div>
		</form>
<?php
}
?>

get_my_taxonomies は以前の記事で書いた、組み込み以外のカスタムタクソノミーを取得する自作の関数です。

フォームを表示したい場所に my_searchform() を記述するだけです。

関数内では、カスタムタクソノミーで foreach して、登録されている件数の多い順に、タームをチェックボックスとして表示しています。

ここで重要なのが input で「name=”タクソノミー名[]”」と「[]」をつけてやることです。これで配列としてタームが格納されるようです。

あとは $_GET[$taxonomy] で選択された情報を取得して、検索結果ページのフォームでも検索条件を維持するようにしました。

最初に見ていたサイトで得た重要な情報の一つとして、「検索結果である(is_search)」と認識してもらうためには検索キーワード(s)を渡してあげないということです。

今回は最後に「フリーワード」としてテキスト検索を入れてますが、それが必要ない場合は以下の内容を追加する必要があります。

<input type="hidden" name="s" id="s">

WordPressではURLのパラメーターに「s=」が入っていたら、is_search と認識してくれるようです。(たぶん)

なので、全件表示ボタンは onclick=”location.href=’(サイトURL)/?s='” としています。

と、このようにフォームを整えてあげることで、検索結果ページとしては特にすることはありませんでした。(ちょっとショック)

ただ一つ、検索結果には固定ページを入れたくなかったので、そこは pre_get_posts を使ってメインクエリを編集しました。

/* --------------------------------------------------
// メインクエリ編集
-------------------------------------------------- */
add_action( 'pre_get_posts','pre_get_posts_custom' );
function pre_get_posts_custom( $query ) {

	if( is_admin() || !$query->is_main_query() ){
		return;
	}

	if( $query->is_search() ){// 検索結果ページ
		$query->set( 'post_type', 'post' );
		return;
	}

}

以上、大変勉強になった案件でした。

タイトルとURLをコピーしました