Craft CMS で手軽にページ分割付きの検索ページを作る方法

Craft CMS では、とても簡単にキーワード検索のフォームを設置することができます。

今回はその方法をご紹介します。

検索フォームを設置

ページのどこかに下記のような検索フォームを設置します。

<form action="{{ url('search/results') }}">
  <input type="search" name="q" placeholder="検索">
  <input type="submit" value="検索">
</form>

検索結果を表示するページを作成

検索結果を表示するテンプレートを作成します。

今回は、上記の form タグの action 属性に {{ url('search/results') }} と指定しているので、検索結果ページは下記のように設置します。

craft/template/search/results.twig

なお、Craft のテンプレートについて知りたい方は @BUN さんの下記の記事を参考にしてください。

results.twig には下記のように書きます。なお、ここでは _layout_base というベーステンプレートを継承しています。

{# ベーステンプレートとして _layout_base を継承 #}
{% extends '_layout_base' %}
{# 出力対象のエントリを変数にセット #}
{% set query = craft.request.getParam('q') %}
{% set results = craft.entries({
  section: 'blog',
  search: {
    query: query,
    subLeft: true,
    subRight: true,
    order: 'score'
  }
}) %}
{# results を20件ごとにページ分割 #}
{% paginate results.limit(20) as pageInfo, pageEntries %}
{% block mainContent %}
  <div role="main">
    <section id="posts">
      <h2 style="padding-bottom: 20px;">検索結果</h2>
    {% if results|length %}
      <p>{{ results|length }} 件見つかりました。</p>
        <ol>
          {% for entry in pageEntries %}
            <li>
              <a href="{{ entry.url }}">
                <time datetime="{{ entry.postDate.iso8601 }}">{{ entry.postDate|date("Y年m月d日") }}</time>
                <div>
                  <span class="title">{{ entry.title }}</span>
                </div>
              </a>
            </li>
          {% endfor %}
        </ol>
    {% else %}
      <p>「{{ query }}」が見つかりませんでした。</p>
    {% endif %}
    </section>
    <article class="entry">
      <nav class="pagination">
        <ul>
        {% if pageInfo.prevUrl %}
          <li><a rel="prev" href="{{ pageInfo.prevUrl }}?q={{ query }}">前のページ</a></li>
        {% endif %}
        {% if pageInfo.nextUrl %}
          <li><a rel="next" href="{{ pageInfo.nextUrl }}?q={{ query }}">次のページ</a></li>
        {% endif %}
        </ul>
      </nav>
    </article>
  </div>
{% endblock %}

 解説

順を追って解説していきます。

ベーステンプレートを継承

{# ベーステンプレートとして _layout_base を継承 #}
{% extends '_layout_base' %}

ベーステンプレートを継承します。

出力対象のエントリを変数にセット

{# 出力対象のエントリを変数にセット #}
{% set query = craft.request.getParam('q') %}

まず q パラメータの値を変数 query にセットします。

{% set results = craft.entries({
  section: 'blog',
  search: {
    query: query,
    subLeft: true,
    subRight: true,
    order: 'score'
  }
}) %}

上記のように entries に取得する条件をセットしてエントリを取得します。

  • sectionblog セクションに限定
  • query に変数 query を渡す
  • subLeftsubRighttrue をセットして、検索キーワードの左右にワイルドカードを付けたのと同じ状態する( *キーワード* と同じ)
  • order'score' をセットしてスコア順に並べる

20件ごとにページ分割する

{# results を20件ごとにページ分割 #}
{% paginate results.limit(20) as pageInfo, pageEntries %}

これで 20 件ごとにページ分割できるようにします。

検索結果を表示

{% block mainContent %}
  <div role="main">
    <section id="posts">
      <h2 style="padding-bottom: 20px;">検索結果</h2>
    {% if results|length %}
      <p>「{{ query }}」が {{ results|length }} 件見つかりました。</p>
        <ol>
          {% for entry in pageEntries %}
            <li>
              <a href="{{ entry.url }}">
                <time datetime="{{ entry.postDate.iso8601 }}">{{ entry.postDate|date("Y年m月d日") }}</time>
                <div>
                  <span class="title">{{ entry.title }}</span>
                </div>
              </a>
            </li>
          {% endfor %}
        </ol>
    {% else %}
      <p>「{{ query }}」が見つかりませんでした。</p>
    {% endif %}
    </section>

検索結果を表示します。ポイントだけ解説します。

{% if results|length %}...{% else %}...{% endif %} で検索結果がある場合とない場合を分岐しています。結果件数は {{ results|length }} で出力できます。

{% for entry in pageEntries %}...{% endfor %} で現在のページのエントリをループします。

ページ送りを表示

ページ送りのリンクを表示します。

    <article class="entry">
      <nav class="pagination">
        <ul>
        {% if pageInfo.prevUrl %}
          <li><a rel="prev" href="{{ pageInfo.prevUrl }}?q={{ query }}">前のページ</a></li>
        {% endif %}
        {% if pageInfo.nextUrl %}
          <li><a rel="next" href="{{ pageInfo.nextUrl }}?q={{ query }}">次のページ</a></li>
        {% endif %}
        </ul>
      </nav>
    </article>
  </div>
{% endblock %}

ページ送りのリンクを {{ pageInfo.prevUrl }}?q={{ query }} のようにしてパラメータを渡して挙げるのがポイントです。

これだけでページ送り付きの検索ページを作ることができました。とても手軽ですね!

以上です。

  • このエントリーをはてなブックマークに追加
Just a second...