べんりワザ・WordPressのカスタマイズの土台

検索フォームと検索結果ページを整える

サイト内検索を使いやすくする方法。検索フォームの自作、検索結果ページ(search.php)の作り方、投稿タイプを絞る指定、空欄で検索されたときの対処までまとめました。

サイト内検索は、フォームと結果ページの2つを整えるだけで使い勝手が大きく変わります。まずは動く最小構成から。

<?php get_search_form(); ?>

これで標準のフォームが出ます。見た目を変えたいときは、テーマにsearchform.phpを作るとその内容が使われます。

検索フォームを自作する

<form role="search" method="get" class="search-form" action="<?php echo esc_url(home_url('/')); ?>">
  <label>
    <span class="sr-only">サイト内を検索</span>
    <input type="search" name="s" value="<?php echo esc_attr(get_search_query()); ?>"
           placeholder="キーワードを入力" required>
  </label>
  <button type="submit">検索</button>
</form>

必須の条件は3つです。

  • method="get"
  • actionhome_url('/')
  • 入力欄のnames

この3つが揃っていれば、あとのマークアップは自由です。valueget_search_query()を入れておくと、検索後もキーワードが残るので使いやすくなります。

検索結果ページ(search.php)

<?php get_header(); ?>

<main class="section">
  <h1>「<?php echo esc_html(get_search_query()); ?>」の検索結果</h1>

  <?php if (have_posts()) : ?>
    <?php global $wp_query; ?>
    <p class="result-count"><?php echo esc_html(number_format($wp_query->found_posts)); ?>件見つかりました</p>

    <ul class="search-results">
      <?php while (have_posts()) : the_post(); ?>
        <li>
          <a href="<?php the_permalink(); ?>">
            <?php if (has_post_thumbnail()) : ?>
              <?php the_post_thumbnail('thumbnail'); ?>
            <?php endif; ?>
            <h2><?php the_title(); ?></h2>
            <p><?php echo esc_html(wp_trim_words(get_the_excerpt(), 80, '…')); ?></p>
          </a>
        </li>
      <?php endwhile; ?>
    </ul>

    <?php the_posts_pagination(['prev_text' => '前へ', 'next_text' => '次へ']); ?>

  <?php else : ?>
    <p>「<?php echo esc_html(get_search_query()); ?>」に一致する記事は見つかりませんでした。</p>
    <p>キーワードを短くする、別の言い方を試すとヒットしやすくなります。</p>
    <?php get_search_form(); ?>
  <?php endif; ?>
</main>

<?php get_footer(); ?>

0件のときの案内を必ず用意します。「見つかりませんでした」で終わらせず、もう一度検索できるフォームや人気記事への導線を置くのが親切です。

べんりワザWordPressのページ送り(ページネーション)の出し方ページ送りの出し方はこちらべんりワザ抜粋(the_excerpt)の文字数と「続きを読む」を変える抜粋の文字数を調整する方法はこちら

検索対象を絞る(固定ページや添付を除く)

既定では、公開されている投稿タイプがまとめて検索されます。投稿と商品だけにしたいならpre_get_postsで指定します。

function my_search_filter($query) {
  if (is_admin() || !$query->is_main_query() || !$query->is_search()) {
    return;
  }
  $query->set('post_type', ['post', 'shohin']);
  $query->set('posts_per_page', 20);
}
add_action('pre_get_posts', 'my_search_filter');

is_admin()is_main_query()のガードは必須です。これが無いと管理画面の検索やサブループまで巻きこみます。

べんりワザループの外で投稿を取得する方法(WP_Query)pre_get_postsの使い方と注意点はこちら

投稿タイプをフォーム側から切り替えることもできます。

<input type="hidden" name="post_type" value="shohin">

商品ページ用の検索フォームでは、これを入れておくと商品だけを検索できます。

カテゴリや分類で絞りこめる検索フォーム

<form role="search" method="get" action="<?php echo esc_url(home_url('/')); ?>">
  <input type="search" name="s" value="<?php echo esc_attr(get_search_query()); ?>">

  <select name="season">
    <option value="">季節を選ぶ</option>
    <?php foreach (get_terms(['taxonomy' => 'season', 'hide_empty' => false]) as $term) : ?>
      <option value="<?php echo esc_attr($term->slug); ?>"
        <?php selected(get_query_var('season'), $term->slug); ?>>
        <?php echo esc_html($term->name); ?>
      </option>
    <?php endforeach; ?>
  </select>

  <button type="submit">検索</button>
</form>

タクソノミーのquery_varが有効なら、?s=…&season=winterのようなURLで自動的に絞りこまれますselected()は選択状態を復元するWordPressの便利関数です。

べんりワザget_termsでカテゴリ・タームの一覧を出す選択肢の元になるターム一覧の取得はこちら

カスタムフィールドも検索したいとき

WordPressの標準検索は、タイトルと本文(と抜粋)だけが対象です。カスタムフィールドの値は検索されません。

  • タクソノミーに置きかえる——絞りこみで使う情報は分類にしておくと検索性が上がる
  • 検索拡張プラグインを使う——カスタムフィールドやPDF内テキストまで対象にできるものがある
  • posts_searchフィルタで拡張する——SQLに手を入れるため上級向け

まずは「検索されたい情報を本文かタクソノミーに入れておく」という設計側の工夫がいちばん確実です。

べんりワザカスタムタクソノミーの作り方(register_taxonomy)絞りこみの軸をタクソノミーにする設計はこちら

検索結果のURLをきれいにする

?s=キーワードではなく/search/キーワード/にしたい場合は、リダイレクトで変換できます。

add_action('template_redirect', function () {
  if (is_search() && !empty($_GET['s'])) {
    $url = home_url('/search/' . urlencode(get_query_var('s')) . '/');
    if (untrailingslashit($_SERVER['REQUEST_URI']) !== untrailingslashit(wp_make_link_relative($url))) {
      wp_safe_redirect($url, 301);
      exit;
    }
  }
});

見た目は整いますが必須ではありません。検索結果ページは検索エンジンにインデックスさせない設計が一般的なので、優先度は低めに考えてかまいません。

まとめ

  1. フォームはsearchform.phpに置くとget_search_form()から使われる。name="s"が必須
  2. 結果ページはsearch.php0件のときの案内と再検索フォームを必ず用意する
  3. 検索対象はpre_get_postspost_typeを指定して絞る(ガードを忘れない)
  4. 標準検索はタイトルと本文だけ。絞りこみたい情報はタクソノミーにしておく

検索が使えるサイトは、記事が増えたときの回遊力がまるで違います。

よくある質問

検索フォームのHTMLを自分で書きたいです
テーマにsearchform.phpを作ると、get_search_form()がそのファイルの内容を出力します。フォームはmethod="get"、actionにhome_url('/')、入力欄のnameを"s"にするのが必須の条件です。
検索結果に固定ページや添付ファイルを含めたくありません
pre_get_postsで検索時のpost_typeを指定します。$query->set('post_type', ['post','shohin'])のように、検索対象にしたい投稿タイプだけを渡します。
検索欄を空で送信するとトップページに飛んでしまいます
WordPressの仕様です。空の検索を検索結果ページに向けたい場合は、pre_get_postsでis_searchかつ検索語が空のときにsを空文字として扱う指定を足すか、フォーム側で未入力の送信を止めます。
検索結果の件数を表示したいです
global $wp_query; を使い、$wp_query->found_postsで総件数が取れます。「〇件見つかりました」の表示に使えます。