Craft CMS で日付や数値を指定してエントリを絞り込む

これは Craft CMS Advent Calendar 2017 8日目の記事です。
今回は備忘録を兼ねて、日付や数値の範囲を指定しつつ Twig テンプレートでエントリを絞り込む方法について、ご紹介します。

投稿日で絞り込む

投稿日で絞り込むには、2つの方法があります。

after / before を利用する場合

サンプルとして {{ now }} で取得できる日付を利用して、1年前に投稿されたエントリを取得してみます。

{# 1年前の日付をセット #}
{% set targetDate = now | date_modify('-1 year') %}
{# 1年前の翌日をセット #}
{% set targetNextDate = targetDate | date_modify('+1 day') %}
{# after / before で日付を絞り込み #}
{% for entry in craft.entries.after(targetDate).before(targetNextDate).find() %}
  {% if loop.first %}<ul>{% endif %}
    <li>{{ entry.title }}</li>
  {% if loop.last %}</ul>{% endif %}
{% endfor %}

now | date_modify('-1 year') で1年前の日付を取得し、変数にセットしたものを利用して targetDate | date_modify('+1 day') でその翌日を取得します。

after は指定日を含み before は指定日を含まないため、1年前に投稿されたエントリだけを絞り込めます。
指定可能な日時の書式なども掲載されていますので、公式ドキュメントも参考にしてください。

craft.entries | Templating Reference | Craft CMS
https://craftcms.com/docs/templating/craft.entries#after

postDate を利用する場合

こちらは、2017年12月1日から今日までのエントリを絞り込んでみます。

{% for entry in craft.entries.postDate('and', '>= 2017-12-01', '< 2017-12-09').find() %}
  {% if loop.first %}<ul>{% endif %}
    <li>{{ entry.title }}</li>
  {% if loop.last %}</ul>{% endif %}
{% endfor %}

ポイントとなる .postDate('and', '>= 2017-12-01', '< 2017-12-09') の日付指定は .after('2017-12-01').before('2017-12-09') と記述した場合と同じ結果になります。

数値で絞り込む

「数字」タイプのフィールドの場合、先の postDate と同様の記述で範囲指定が可能です。
下記サンプルでは num_price というハンドル名のフィールドが 1000〜9999 の値を持つエントリを絞り込みます。

{% for entry in craft.entries.num_price('and', '>= 1000', '< 10000').find() %}
  {% if loop.first %}<ul>{% endif %}
    <li>{{ entry.title }}</li>
  {% if loop.last %}</ul>{% endif %}
{% endfor %}

他にも .num_price('>= 1000').num_price('= 1000') のように単独の条件を指定することもできます。

年や月で絞り込む

最後に、年別や月別アーカイブの一覧をサンプルにしてみます。

{# すべてのエントリを取得 #}
{% set allEntries = craft.entries.limit(null) %}
{# 年ごとにグループ化したエントリをループ処理 #}
{% for year, yearlyEntries in allEntries | group("postDate.year") %}
  <h2><a href="/?year={{ year }}">{{ year }}</a></h2>
  <ul>
    {# 月ごとにグループ化したエントリをループ処理 #}
    {% for month, monthlyEntries in yearlyEntries | reverse | group("postDate | date('m')") %}
      <li><a href="/?year={{ year }}&month={{ month }}">{{ month | replace('/^0/', '') }}月</a></li>
    {% endfor %}
  </ul>
{% endfor %}

allEntries | group("postDate.year") では、投稿年をキー・年ごとのエントリを値とするグループ化を行なっています。

このループ処理内で yearlyEntries | reverse | group("postDate | date('m')") とすることで、さらに月ごとにグループ化します。このとき、デフォルトでは月の出力が逆(12月が先頭)になってしまうため reverse フィルタを利用しています。

なお、公式ドキュメントではアーカイブをページ分割する方法なども紹介されていますので、あわせてご覧ください。

Creating an “Archive” Page for Entries | Support | Craft CMS
https://craftcms.com/support/entry-archive

まとめ

書き方を覚えれば、比較的柔軟に絞り込みができるのはやはり便利ですね。
また便利そうな記述方法を思いついたら、共有します。