これは Craft CMS Advent Calendar 2016 14日目の記事です。
今回は、エントリの一覧を出力する際のテンプレートの書き方を見ていきます。
主にエントリの絞り込みに関する内容をまとめるため、フィールドの出力については次回改めて解説する予定です。
エントリの出力を試す
はじめに、すべてのエントリを出力してみましょう。
前回作成した blog/index.twig
を開き、{% block mainContent %}
と {% endblock %}
内の任意の箇所に下記コードを入力の上、確認してみてください。
すべてのエントリを出力
{% for entry in craft.entries %}
<h2><a href="{{ entry.url }}">{{ entry.title }}</a></h2>
{% endfor %}
サンプルは {% for %}
タグのループ処理で個々のエントリを entry
にセットし、そこから {{ entry.title }}
(タイトル)や {{ entry.url }}
(パーマリンク)を出力しています。
craft.entries
はエントリ取得用のオブジェクトで、追加されたパラメータにあわせてエントリが絞り込まれます。
最新3件のエントリを出力
{% for entry in craft.entries.limit(3) %}
<h2><a href="{{ entry.url }}">{{ entry.title }}</a></h2>
{% endfor %}
limit
パラメータで、出力件数を指定できます。
指定した投稿日に含まれるエントリを出力
{% for entry in craft.entries.after('2016-05-02').before('2016-05-04') %}
<h2><a href="{{ entry.url }}">{{ entry.title }}</a></h2>
{% endfor %}
after
と befor
パラメータを組み合わせることで、指定した期間のエントリのみに絞り込むことができます。
なお、セットできるパラメータについては、公式リファレンスも参照してみてください。
craft.entries | Templating Reference | Craft CMS:
https://craftcms.com/docs/templating/craft.entries
複雑な絞り込みをする前に
{% set %}
タグで取得したオブジェクトを一旦変数にセットしておくと、条件の設定と出力のループ処理を分けて記述できるため、コードの可読性が高くなります。
{# 出力対象のエントリを変数にセット #}
{% set filterdEntries = craft.entries %}
{# 出力対象のエントリをループ処理 #}
{% for entry in filterdEntries %}
<h2><a href="{{ entry.url }}">{{ entry.title }}</a></h2>
{% endfor %}
以降のサンプルは、この {% set %}
タグ部分についての解説となります。
エントリの絞り込み
では、よく使いそうな絞り込みを見てみましょう。
セクションで絞り込む
{% set filterdEntries = craft.entries.section('work') %}
セクションによる絞り込みは section
パラメータと 設定 > セクション
の ハンドル
列に書かれた文字列の組み合わせることで可能になります。
サンプルの場合、Work
セクションのエントリだけを取得できます。
同一エントリをタイトル、ID、スラグのいずれかで絞り込む
Services セクション、かつ、タイトルが「Design」のエントリをセット
{% set filterdEntries = craft.entries.section('services').title('Design') %}
ID = 129 のエントリをセット
{% set filterdEntries = craft.entries.id(129) %}
Services セクション、かつ、スラグが「design」のエントリをセット
{% set filterdEntries = craft.entries.section('services').slug('design') %}
特定のエントリを取得する場合によく使う記述で、3つとも同じエントリを取得できます。
エントリのタイトルなど同一のものが存在する場合は、 section
パラメータなどと組み合わせると良いでしょう。
関連付けされたエントリで絞り込む
{# ID = 129 のエントリを取得 #}
{% set relatedEntry = craft.entries.id(129) %}
{# Work セクションの「Services Performed」フィールドに relatedEntry がセットされているエントリを取得 #}
{% set filterdEntries = craft.entries.section('work').relatedTo({
targetElement: relatedEntry,
field: 'servicesPerformed'
}) %}
フィールドタイプがエントリ、ファイル管理、カテゴリー、タグ、ユーザのいずれかに該当する場合、セットされた内容を relatedTo
パラメータで絞り込むことができます。サンプルは Services Performed
フィールドに Design
エントリが関連付けされている Work
セクションのエントリを取得するための記述です。
{% set %}
タグを2つ記述し、targetElement
で参照している点がポイントです。
{# ID = 12345 のカテゴリを取得 #}
{% set relatedCategory = craft.categories.id(12345) %}
このように、対象となる要素とフィールドのハンドル名を調整すれば、カテゴリーなどでも同様に絞り込めます。
なお、カテゴリーとタグの両方を指定するなど複合的な指定も可能ですので、公式リファレンスを確認してみてください。
Relations | Documentation | Craft CMS:
https://craftcms.com/docs/relations
ページを分割するには?
ページ分割は、Craft CMS の独自タグを利用します。
{# News セクションのエントリを取得 #}
{% set filterdEntries = craft.entries.section('news') %}
{# filterdEntries を3件ごとにページ分割 #}
{% paginate filterdEntries.limit(3) as pageInfo, pageEntries %}
{# リクエストされたページのエントリを出力 #}
{% for entry in pageEntries %}
{% if loop.first %}<ul>{% endif %}
<li><a href="{{ entry.url }}">{{ entry.title }}</a></li>
{% if loop.last %}</ul>{% endif %}
{% endfor %}
{# ページャ #}
{% if pageInfo.prevUrl %}<a href="{{ pageInfo.prevUrl }}">Previous</a>{% endif %}
{% if pageInfo.nextUrl %}<a href="{{ pageInfo.nextUrl }}">Next</a>{% endif %}
まず、絞り込んだエントリを {% paginate %}
タグでページあたりの表示件数を指定して分割します。
エントリの出力は {% paginate %}
タグで指定したオブジェクトをループ処理し、任意の場所にページャを記述する流れです。
従来のエントリの出力を少しカスタマイズするだけで対応できるので、判りやすいですね。
なお、公式サイトのリファレンスでは pageInfo
にセットされる変数を確認できます。あわせて、ページャのマークアップをページ番号のリンクテキストにするためのサンプルコードが紹介されていますので、ぜひ確認してみてください。
{% paginate %} | Templating Reference | Craft CMS:
https://craftcms.com/docs/templating/paginate
blog/index.twig の最終的なコード
当初 ブログ
セクションの一覧にする予定でしたが、エントリが登録されてない可能性があるため、News
セクションの一覧を出力する形にしてみました。
{#
# ブログ:インデックス テンプレート
# -----------------
#
# 「ブログ」セクションの一覧ページ用テンプレート。
-#}
{# ベーステンプレートとして _layout_bootstrap を継承 #}
{% extends '_layout_bootstrap' %}
{# このテンプレートのみに追加する、スタイル定義をセット #}
{% set blogCss %}
body {
padding-top: 50px;
}
{% endset %}
{% includeCss blogCss %}
{# このテンプレートの mainContent の内容をセット #}
{% block mainContent %}
<div class="jumbotron">
<div class="container">
<h1>Hello, world!</h1>
<p>This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a></p>
</div>
</div>
<div class="container">
<h1>News セクションのエントリ一覧</h1>
{# News セクションのエントリを取得 #}
{% set filterdEntries = craft.entries.section('news') %}
{# filterdEntries を3件ごとにページ分割 #}
{% paginate filterdEntries.limit(3) as pageInfo, pageEntries %}
{# リクエストされたページのエントリを出力 #}
{% for entry in pageEntries %}
{% if loop.first %}<ul>{% endif %}
<li><a href="{{ entry.url }}">{{ entry.title }}</a></li>
{% if loop.last %}</ul>{% endif %}
{% endfor %}
{# ページャ #}
{% if pageInfo.prevUrl %}<a href="{{ pageInfo.prevUrl }}">Previous</a>{% endif %}
{% if pageInfo.nextUrl %}<a href="{{ pageInfo.nextUrl }}">Next</a>{% endif %}
</div>
{% endblock %}
{% for %}
タグには loop.first
と loop.last
の場合に ul
タグを出力するよう、分岐を加えてあります。
まとめ
ここでは、一覧ページのテンプレートを想定し、エントリの絞り込み方法について解説してみました。
基本を抑えれば、意外と簡単に柔軟な絞り込みができることを感じてもらえたら、嬉しいですね。
次回は、エントリの詳細用テンプレートを題材に、フィールドの出力について解説してみようと思います。