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

Craft CMS で検索ページを作る方法をご紹介します。

Craft CMS Logo

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 }} のようにしてパラメータを渡して挙げるのがポイントです。

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

以上です。

Published 2017-05-01
Updated 2019-06-25