WordPress

WordPress サイト内検索機能の実装方法

WordPress サイト内検索機能の実装方法

WordPress でサイト内検索機能を実装するための「検索フォーム」や「検索結果ページ」の実装方法を紹介します。
例えば、投稿記事の検索や、カスタム投稿で登録した製品情報を検索したい時に便利方法です。

サイト内検索機能を実装するためには、最低限以下の二つが必要になります。
1)検索フォームエリア・テンプレート
2)検索結果ページテンプレート

そこでこの記事では「検索フォームの設置」から「検索結果ページ」の実装方法を順番に解説していきます。合わせて、よくリクエストされるカスタマイズ方法もご紹介します。

  1. 検索フォームのテンプレートを作成
    1. get_search_form で検索フォームの設置
  2. 検索結果ページの作成
  3. 検索結果ページのタイトルをカスタマイズする
  4. 投稿タイプを指定して検索対象を絞り込む
  5. カテゴリやカスタムフィールドも検索対象にする
  6. 検索結果ページで検索フォームに検索キーワードを残す方法
  7. 検索ワードをハイライトして表示する方法
  8. 検索結果の表示件数を変更する方法
  9. 複数キーワード検索ができない時の対処方法
  10. WordPress で検索結果を日付順や順序順にする方法
    1. 検索結果を日付順で表示する方法
    2. 検索結果を日付順(降順)で表示する方法
    3. 検索結果を日付順(昇順)で表示する方法
    4. 検索結果を順序順で表示する方法
  11. クロスサイトスクリプティングの対策方法

検索フォームのテンプレートを作成

まずは検索フォームエリア・テンプレートを用意します。
テーマディレクトリにテンプレートファイル searchform.php を作成、作ったテンプレートファイルに次のコードを追加してください。

<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
<input type="text" name="s" id="s" placeholder="SEARCH"/>
<button type="submit">検索する</button>
</form>

ここでは汎用的に使いまわせるテンプレートとして紹介していますが、フォームのコードを直接他のテンプレートに記載しても問題ありませんが、テンプレートファイルにすると色々なページで流用できるのでとても便利です。

placeholderの文言「SEARCH」 や buttonの文言「検索」は自由に変更してください。

get_search_form で検索フォームの設置

作った検索フォームのテンプレートは、関数 get_search_form で好きな場所に呼び出すことができます。
次のコードを、検索フォームを設置したいテンプレートに追加します。

<?php get_search_form(); ?>

検索結果ページの作成

次に検索結果を表示するためのページテンプレート search.php を作成します。
テーマディレクトリにテンプレートファイル search.php ファイルを作成、作ったテンプレートファイルに次のコードを追加します。

<?php if (have_posts()): ?>
<?php
if (isset($_GET['s']) && empty($_GET['s'])) {
echo '検索キーワード未入力'; // 検索キーワードが未入力の場合のテキストを指定
} else {
echo '“'.$_GET['s'] .'”の検索結果:'.$wp_query->found_posts .'件'; // 検索キーワードと該当件数を表示
}
?>
<ul>
<?php while(have_posts()): the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>"><?php echo get_the_title(); ?></a>
</li>
<?php endwhile; ?>
</ul>
<?php else: ?>
検索されたキーワードにマッチする記事はありませんでした
<?php endif; ?>

これでひとまず完成になります。
サイト内検索の検索対象は「タイトル」「本文・抜粋」になるので、投稿のタイトルなどを入力して動作を確認してみましょう。

検索結果ページのタイトルをカスタマイズする

検索結果ページのタイトルの表示に wp_title を使用すると、定型のタイトルが表示されるので、このタイトルをカスタマイズしたい場合は次のコードを functions.php に追加します。

/*【出力カスタマイズ】検索結果のタイトルをカスタマイズ */
function wp_search_title($search_title){
if(is_search()){
$search_title = '「'.get_search_query().'」の検索結果';
}
return $search_title;
}
add_filter('wp_title','wp_search_title');

投稿タイプを指定して検索対象を絞り込む

投稿タイプを指定して検索対象を絞り込む方法を紹介します。
例えば、投稿(post)と固定ページ(page)の他に、カスタム投稿(blog)を検索対象にしたい場合、
次のコードを functions.php に追加します。

/*【出力カスタマイズ】検索対象をカスタム投稿タイプで絞り込む */
function my_pre_get_posts($query) {
if ( !is_admin() && $query->is_main_query() && $query->is_search() ) {
$query->set( 'post_type', array('post','page','blog') );
}
}
add_action( 'pre_get_posts','my_pre_get_posts' );

上記コードの4行目に記載している $query->set('post_type', array('post', 'page', 'blog')); の投稿タイプの指定を編集します。
例えばカスタム投稿タイプ「ブログ(スラッグ:blog)」を加える場合は array('post', 'page', 'blog') のようにカンマ区切りでスラッグを追加します。

register_post_type を使用している場合

カスタム投稿タイプを function.php 内で register_post_type 関数を使って追加している場合は、パラメーターに exclude_from_search を加えて検索対象に含める必要があります。
例えば、カスタム投稿タイプを検索に含める場合は register_post_type の値を false にします。

'exclude_from_search' => false, // false 検索対象に含める

逆に、検索に含めない場合は register_post_type の値を true にします。

'exclude_from_search' => true,

末尾のカンマは挿入箇所に応じて調整してください。

カテゴリやカスタムフィールドも検索対象にする

カスタムフィールドやカテゴリなどを検索対象に含める場合はプラグインを使うと簡単です。
例えば Search Everything などは導入が簡単でおすすめですが、サポートが終了しているプラグインも多いため注意が必要です。

カスタムフィールドやカテゴリを検索対象とした場合、and検索が意図した通りに動かない場合があります。実装を決める際は、検証作業を入念に行うことをおすすめします。

検索結果ページで検索フォームに検索キーワードを残す方法

検索結果ページに遷移すると検索フォームに入力されたキーワードは消えてしまいます。
最初に検索したキーワードを残して検索を続けたい場合もあるので、「検索フォームのテンプレートを作成」で紹介したコードを、キーワードが残るようにカスタマイズします。

<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
<input type="text" name="s" id="s" placeholder="<?php if(!is_search()){ echo 'SEARCH';} ?>" value="<?php if(is_search()){ echo get_search_query();} ?>"/>
<button type="submit">検索する</button>
</form>

ここでは、input タグの placeholder と value の値にif文を追加して、検索結果ページへ遷移した後に検索キーワードを取得して代入する処理を加えています。

検索ワードをハイライトして表示する方法

検索結果ページで検索ワードをハイライトして強調表示する方法を紹介します。
例えば、検索結果ページでタイトルと本文(または抜粋)が表示される場合、表示されるテキスト内に検索キーワードが含まれていたら、mark タグで囲うようにするには、次のコードを function.php に追加します。

/*【検索カスタマイズ】検索ワードをハイライトする */
function highlight_search_word($text){ // 関数「highlight_search_word」を定義
if(is_search()){ // 検索ページが表示されている時に実行
$keys = implode('|', explode(' ', get_search_query())); // 検索ワードを分割して配列にして返す
$text = preg_replace('/('. $keys .')/iu', '<mark>
/*【検索カスタマイズ】検索ワードをハイライトする */
function highlight_search_word($text){ // 関数「highlight_search_word」を定義
if(is_search()){ // 検索ページが表示されている時に実行
$keys = implode('|', explode(' ', get_search_query())); // 検索ワードを分割して配列にして返す
$text = preg_replace('/('. $keys .')/iu', '<mark>\0</mark>', $text); // 該当ワードを mark で囲む
}
return $text; // 変更した値を呼び出し元に戻す
}
add_filter('the_title', 'highlight_search_word'); // タイトルに適用
add_filter('the_content', 'highlight_search_word'); // 本文に適用
add_filter('the_excerpt', 'highlight_search_word'); // 抜粋に適用
</mark>', $text); // 該当ワードを mark で囲む
}
return $text; // 変更した値を呼び出し元に戻す
}
add_filter('the_title', 'highlight_search_word'); // タイトルに適用
add_filter('the_content', 'highlight_search_word'); // 本文に適用
add_filter('the_excerpt', 'highlight_search_word'); // 抜粋に適用

画像のaltにタグが挿入されてしまう時の回避方法

この方法の場合、検索結果ページで表示される投稿の画像の altget_the_title() を使っていると、alt にタグが挿入されてしまいます。
これを回避するためには strip_tags() を使って、タイトルからタグを除く処理を追加します。

<?php echo strip_tags(get_the_title()); ?>

検索結果の表示件数を変更する方法

何も設定をしない場合は管理画面の設定「表示設定」の最大投稿件数が表示件数として反映されますが、時には表示件数を変更したい場合もあるかと思います。
簡単に検索結果の表示件数を変更したい場合は query_posts() を使用します。
検索結果テンプレートの search.php の have_posts 上に query_posts() の記述を追加します。
次のコードは、検索結果の表示件数を1ページあたり12件にする方法です。

<?php query_posts($query_string.'&posts_per_page=12'); ?>
<?php if (have_posts()): ?>
-- 以下省略 --

複数キーワード検索ができない時の対処方法

複数のキーワード検索する時に「全角スペース」でキーワードを区切ると、全角スペースが文字扱いされて意図した検索ができない場合があります。
そんな時はプラグイン「WP Multibyte Patch」をインストールして有効化してください。
WordPress を手動でインストールするとこのプラグインのインストールを忘れがちなので気をつけましょう。

WordPress で検索結果を日付順や順序順にする方法

WordPress で検索結果を日付順や順序順にする方法を紹介します。
検索結果の順番をカスタマイズするにはフィルターフックを利用します。

検索結果を日付順で表示する方法

検索結果を日付順で表示する場合は date(post_dateでも可) を指定します。
例えば、検索結果を日付順に表示したい場合は次のコードを function.php に追加します。

/*【出力カスタマイズ】検索結果をカスタマイズ */
function my_pre_get_posts($query) {
if ( !is_admin() && $query->is_main_query() && $query->is_search() ) {
$query->set( 'orderby', 'date' ); // 日付順
}
}
add_action( 'pre_get_posts','my_pre_get_posts' );

上記のコードは先に紹介している「投稿タイプを指定して検索対象を絞り込む」と重複します。
先の投稿タイプの絞り込みを行なっている場合は以下の部分をフィルターフックに追記してください。

-- 以下省略 --
$query->set( 'orderby', 'date' ); // 日付順
-- 以下省略 --

検索結果を日付順(降順)で表示する方法

検索結果を日付順(降順)で表示する場合は order で desc を指定します。
例えば、検索結果を日付順(降順)に表示したい場合は次のコードを、先に紹介した「日付順」の項目を参考に function.php に追加します。

-- 以下省略 --
$query->set( 'order', 'DESC' ); // 最高から最低へ降順 (3, 2, 1, c, b, a)
-- 以下省略 --

検索結果を日付順(昇順)で表示する方法

検索結果を日付順(昇順)で表示する場合は order と asc を指定します。
例えば、検索結果を日付順(昇順)に表示したい場合は次のコードを、先に紹介した「日付順」の項目を参考に function.php に追加します。

-- 以下省略 --
$query->set( 'order', 'ASC' ); // 最低から最高へ昇順 (1, 2, 3, a, b, c)
-- 以下省略 --

検索結果を順序順で表示する方法

検索結果を順序順で表示する場合は menu_order を指定して対応します。
例えば、検索結果を順序順に表示したい場合は次のコードを、先に紹介した「日付順」の項目を参考に function.php に追加します。

-- 以下省略 --
$query->set( 'orderby', 'rand' ); // ランダムで並び替え
-- 以下省略 --

クロスサイトスクリプティングの対処方法

サイトの脆弱性検査で「クロスサイトスクリプティング対策」をリクエストされた時の対処方法を紹介します。
対策をしていない場合、次のようなアラートを表示するコードをキーワードに入れて検索すると、検索結果ページで任意のプログラム(下記例の場合はアラート)が動いてしまいます。

<script>alert(document.cookie)</script>

自身のサイトでアラートが表示される場合、悪意あるプログラムも動いてしまう可能性があります。
対処として、プログラムに使われる文字列「&」「’」「”」「<」「」「>」などを、プログラムと認識されないように htmlspecialchars() を使ってエスケープ処理をします。
例えば、検索キーワードを「$_GET[‘s’]」で取得している場合のエスケープ処理は次のようになります。

$str = $_GET['s']; // 検索文字列の取得
$e_str = htmlspecialchars($str, ENT_QUOTES, "utf-8"); // 検索文字列のエスケープ処理
echo $e_str; // 検索文字の表示

検索結果ページなど、結果を出力するエリアに組み込んでください。

まとめ

WordPress でサイト内検索機能を実装するための「検索フォーム」や「検索結果ページ」の実装方法を紹介した。