WordPressで、カスタム投稿ごとに検索結果を変えたり、タームごとに違うレイアウトで表示したり——検索結果テンプレート(search.php)を複数使い分けたい場面があります。
結論から言うと、検索フォームにsearch_typeという値を持たせ、functions.phpのtemplate_includeフックで、その値に応じて読み込むsearch.phpを切り替えることで実現できます。この記事では、その実装方法を解説します。
まず、searchform.phpの中でsearch_typeを指定します。
<form role="search" method="get" id="searchform" class="searchform" action="">
<input type="hidden" name="search_type" value="blog">
<div id="keyword-search-wrap">
<input name="s" id="s" type="text" class="keyword-search" placeholder="例)キーワード" value="" required="required">
</div>
<div id="submit-btn-wrap">
<input name="" type="submit" class="submit-btn" value="検索する">
</div>
</form>
ポイントは2行目の<input type="hidden" name="search_type" value="blog">です。この部分でsearch_typeを指定します。type="hidden"にしているので、画面には表示されません。この例ではblogという値を持たせています。
次に、search_typeがblogのときはsearch-blog.phpが適用されるように、functions.phpに記述します。
// 検索フォームごとに search.php を変える
add_action('template_include', 'my_search_template');
function my_search_template($template)
{
$type = filter_input(INPUT_GET, 'search_type');
$new_template = '';
if ($type) {
switch ($type) {
case 'news':
$new_template = STYLESHEETPATH . '/search-news.php';
break;
case 'blog':
$new_template = STYLESHEETPATH . '/search-blog.php';
break;
default:
$new_template = '';
}
}
if ($new_template) {
if (file_exists($new_template)) {
return $new_template;
}
}
return $template;
}
template_includeフックで、送られてきたsearch_typeの値をswitchで判定し、対応するテンプレートファイルのパスを返しています。指定したファイルが実在する場合(file_exists)だけ差し替え、なければ通常のsearch.phpを使う、という安全な作りです。newsならsearch-news.php、blogならsearch-blog.phpが読み込まれます。
search_typeが付いていない通常の検索や、指定したテンプレートが存在しない場合は、標準のsearch.phpにフォールバックします。この安全策があるので、まずは1種類だけ作って動作を確認し、少しずつフォームを増やしていくと安心です。
別の検索フォームを作りたいときは、searchform-news.phpなどのファイルを作成し、呼び出したい部分で次のように読み込みます。
<div class="searchform-news">
<?php get_template_part('searchform-news'); ?>
</div>
それぞれの検索フォームでsearch_typeの値を変えておけば、フォームごとに異なるsearch-{type}.phpが使われます。ニュース用・ブログ用・実績用……と、用途に応じて検索結果の見せ方を分けられます。
上記のコードで使っているSTYLESHEETPATHは、テーマ(子テーマ)のディレクトリパスを表す定数です。現在はget_stylesheet_directory()を使うのが一般的なので、新しく書く場合はget_stylesheet_directory() . '/search-blog.php'のように置き換えてもよいでしょう。動作はどちらも同じです。
search_typeをhiddenで持たせるtemplate_includeフックで、値に応じてsearch-{type}.phpに振り分けるget_template_partで複数用意できる検索結果をフォームごとに出し分けられると、サイトの情報設計の自由度が上がります。カスタム投稿の多いサイトほど効果的なテクニックなので、ぜひ活用してみてください。