WordPressで特定カテゴリだけの検索機能をテーマに追加

検索
©いらすとや.

WordPressはテーマでサイト内全体から検索する機能があることが多い。テーマに検索機能がなくても例えば検索ウィジェットを使うというのもある。 ただ、サイトが肥大したときに例えば特定のカテゴリだけ検索したい/させたいということがある。検索フォームを拡張して閲覧者にカテゴリを選ばせるという方法もあるが、それって意外と閲覧者にとっては不親切。例えば、あるカテゴリ表示専用テンプレートがあって、そこにある検索フォームで検索するとそのカテゴリの記事だけが検索対象になるというのがわかり易いかと。

とあるカテゴリ表示専用のテーマ内テンプレートに検索フォームを書く。
1
2
3
4
5
6
<div class="ui search">
    <form class="search icon input" method="get" action="/search-hogehoge" role="search">
        <input type="search" class="search-field" placeholder="<?php echo esc_attr_x( '検索 …', 'placeholder' ) ?>" value="<?php echo get_search_query() ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" />
        <button type="submit" role="button" class="btn btn-default right"/><i class="search icon" aria-hidden="true"></i></button>
    </form>
</div>

action="/search-hogehoge" と指定したので検索ワードを入力して検索ボタンを押すとhttps://example.com/search-hogehoge が表示される。通常は「 / 」つまりWordPressの大元である/index.phpが指定され、テーマ/search.phpがあればそれ、無ければ戻って/index.phpが使用されて検索結果が表示されることになる。
検索ワードは ?s=検索ワード という形でURLクエリに乗って送られる。(WordPress標準の形式)

テーマディレクトリにsearch-hogehoge.php(任意)のファイルを新規作成する。
テーマによってはサイト内全ての検索結果表示用のsearch.phpがあるかもなのでそれをコピペして作成するのが簡単かも。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
/*
Template Name: Certain-Category-SearchResults
*/
get_header("hogehoge"); //header-hogehoge.php が表示される   ?>
    <main class="bny-main" role="main">
<?php

//検索キーワード取得 普通に$_GET['s']では取得できないのでこの方法で
$enc_int = 'UTF-8';
$enc_ord = 'UTF-8, eucJP-win, SJIS-win';

$s = ''; //検索キーワード
if (isset($GLOBALS["_SERVER"]["REQUEST_URI"])) {
    $s = esc_textarea($GLOBALS["_SERVER"]["REQUEST_URI"]); //URLクエリ(パラメータ)を取得
    if(strpos($s, '?s=') !== false) {
        $s =explode('?s=', $s)[1]; //URLクエリを ?s= で分断してその後半を検索ワードとして抜き出す
        $s = rawurldecode($s);
        $s = mb_convert_encoding($s, $enc_int, $enc_ord);
        $s = trim(mb_convert_kana($s, 's'));
        $s = htmlspecialchars($s, ENT_QUOTES, $enc_int); //検索ワードをエスケープ処理
    } else {
        get_template_part('template-parts/page', 'top');  //テーマディレクトリ内のtemplate-parts/page-top.phpが表示される
        get_footer("hogehoge");  //footer-hogehoge.phpが表示される
        exit;
    }
} else {
    //検索キーワードが無かった場合はトップページとフッタを表示して終了 または見つからなかった旨の表示でも
    get_template_part('template-parts/page', 'top');  //テーマディレクトリ内のtemplate-parts/page-top.phpが表示される
    get_footer("hogehoge"); //footer-hogehoge.phpが表示される
    exit;
}

//クエリーに検索ワードをセット
$args = array(
  's' =>  $s, // 検索キーワード
  'cat' => 18, // 検索対象をカテゴリID 18に限定する
);
//クエリーをセットしたので後は普通に記事表示させる処理でOK

$query = new WP_Query($args);

if (have_posts()) : ?>
    <header class="page-header">
        <h2 class="page-title">
            <?php printf(__('Search Results for: %s', 'mytheme'), '<span>' . $s . '</span>'); ?>
       </h2>
    </header><!-- .page-header -->
<?php endif; ?>

<?php //あとは検索でヒットした記事を表示するループを書く。数行前のif (have_posts()) :から(最後まで) search.phpと同様の処理を書けばOKです ?>

上のコードではカテゴリIDが18のカテゴリに含まれる記事だけが抽出される。
2〜4行目は普通にphpのコメントだが、WordPressでは3行目のTemplate Name: Certain-Category-SearchResultsが意味を持ち、これでCertain-Category-SearchResultsというテンプレートが認識され、そのテンプレートを選択するとこのファイルが使われるようになる。

スラッグが /search-hogehoge の固定記事を作成する。記事のタイトルと本文は無しでも可だがタイトルが空だと判りにくいので何かメモでも入力しておく。その固定記事の「ページ属性」でテンプレートを変更する。その選択するテンプレート上で作成した「Certain-Category-SearchResults」。

WordPressのおせっかい機能のせいで、テーマ/search.php か /index.php以外では検索ワードの「?s=検索ワード」が無効化扱いになるので テーマ/search.php や /index.php以外で検索ワードが受け取りにくい。そのため、普通には検索結果を表示するためのテンプレートファイルを増やすというのができない。
そこで、ちょっとインチキな方法で検索結果テンプレートを作ってみたという内容でした。もっとスマートな方法をご存知の方は教えていただけると嬉しいです。