【Craft 3 サイト構築の基本】「ニュース」セクションの作成(詳細ページテンプレート編)

これは Craft CMS Advent Calendar 2018 13日目の記事です。
連載「サンプル制作で覚える Craft 3 サイト構築の基本」の「ニュース」セクションの作成ということで、詳細ページのテンプレートを作成します。

ここでは、次の作業を行います。

  1. 対象テンプレートの確認
  2. 「画像の変形」を設定
  3. レイアウトテンプレートの微調整
  4. main ブロックの出力
  5. 行列フィールドの出力
  6. 表示の確認

なお、「準備編」の 詳細ページの画面構成 で確認したフィールドを出力する想定ですので、あらかじめ目を通しておくと流れをイメージしやすいと思います。また、工程ごとの差分データは「素材データ専用リポジトリ vol-8 ブランチ」にコミットしてあります。

対象テンプレートの確認

レイアウトテンプレートや共通モジュールを除くと、詳細ページに必要なテンプレートは次の通りです。

templates
├── _partials/
│   ├── article_body.html
│   ├── article_heading.html
│   └── content_header.html
└── news/
    └── _entry.html

templates/_partials 直下の3つのファイルは、他のセクション詳細ページでも共通利用するモジュールです。空のテンプレートファイルを作成しておきます。【参考コミット】

また、セクションごとの詳細ページテンプレートは「設定編」のセクション作成時に テンプレート 欄に入力したパスやファイル名に合わせる必要があります。

「画像の変形」を設定

Craft 3 ではサムネイル画像の生成に関する設定を「画像の変形」として登録し、テンプレート内から ハンドル名 で呼び出すことができます。

設定画面

グローバルナビゲーションから 設定 に移動し、アセット アイコンをクリックします。

画像の変形

サブナビゲーションから 画像の変形 に移動し、新しい画像変換 ボタンをクリックします。

「中サイズ」の作成

新しい画像変形を作る

次の内容を入力してから 保存 ボタンをクリックします。

ラベル
名前中サイズ
ハンドルmedium
モード切り抜き
デフォルトの焦点中央 - 中央
700
高さ424
品質自動
インタレース中なし
画像フォーマットAuto

同様の手順で 小サイズ一覧用サムネイル も追加します。

「小サイズ」の作成

新しい画像変形を作る

次の内容を入力してから 保存 ボタンをクリックします。

ラベル
名前小サイズ
ハンドルsmall
モード切り抜き
デフォルトの焦点中央 - 中央
400
高さ339
品質自動
インタレース中なし
画像フォーマットAuto

「一覧用サムネイル」の作成

新しい画像変形を作る

次の内容を入力してから 保存 ボタンをクリックします。

ラベル
名前一覧用サムネイル
ハンドルthumb
モード切り抜き
デフォルトの焦点中央 - 中央
280
高さ204
品質自動
インタレース中なし
画像フォーマットAuto

「画像の変形」一覧

3つの「画像の変形」が登録されました。

レイアウトテンプレートの微調整

リクエストされたページに合わせて body タグにクラスをセットするため、レイアウトテンプレート(templates/_layout.html)を開き、次の修正を加えます。【参考コミット】

{# body のクラス #}
{% if bodyClass is not defined %}
  {% set bodyClass = craft.app.request.segments | first %}
{% endif %}

<body{% if bodyClass is defined %} class="{{ bodyClass }}"{% endif %}>

変数 bodyClass を継承元のテンプレートで明示的に定義するか、最初のセグメントが自動的にセットされるようになります。

main ブロックの出力

詳細ページテンプレート(templates/news/_entry.html)では、はじめに「meta タイトル」と「main ブロック」を定義しておきます。【参考コミット】

{# meta タイトル #}
{% set metaTitle = entry.title ~ ' | ニュース' %}

セクションの詳細ページであれば、変数 entry でエントリのデータを取得できます。

コーディングデータの流用

コーディングデータ(web/html/news/detail.html)から、メインコンテンツ部分のソースコードをコピーします。【参考コミット】

貼り付けたソースコードのうち、他セクションの詳細ページでも利用するコードをモジュールテンプレートにカット&ペーストします。あわせて、詳細ページテンプレートには {% include %} タグを定義します。【参考コミット】

なお、「記事本文」フィールドの出力先にあたる 「article 本文」モジュール ではソースコードをそのまま利用できないため、モジュールのインクルードのみ定義しておきます。

投稿者名の出力

エントリの投稿者に関するデータは entry.author で取得できます。このデータには、Craft 3 ユーザーの「アカウント」タブやフィールド情報が含まれます。

<p class="center author">{{ entry.author.name }}</p>

ここでは {{ entry.author.name }} とすることで、アカウントのフルネーム(「名」および「姓」フィールドを半角スペースで繋げたテキスト)が出力されます。フルネームが設定されていない場合は、「ユーザー名」となります。【参考コミット】

「コンテンツヘッダー」モジュールのカスタマイズ

「コンテンツヘッダー」モジュールでは、「タイトル」と「メイン画像」を出力します。【参考コミット】

{# 「メイン画像」の取得 #}
{% set image = entry.featuredImage.one() %}

entry.featuredImage.one() で「メイン画像」フィールドのデータを取得しておき

{# 「メイン画像」がセットされている場合のみ出力 #}
{% if image %}
  <section>
    <img class="contain-media" src="{{ image.getUrl({ width: 1440, height: 360 }) }}" alt="{{ image.title }}">
  </section>
{% endif %}

{% if %} タグで実際に画像がセットされている場合のみ出力するよう分岐しています。また image.getUrl() でサムネイル画像を生成しています。

詳細については、公式ドキュメントの「テンプレート内でトランスフォームを定義する」も参考にしてください。

「article 見出し」モジュールのカスタマイズ

「article 見出し」モジュールでは、「大見出し」と「小見出し」を出力します。【参考コミット】

{# 「大見出し」がセットされている場合のみ出力 #}
{% if entry.heading %}
  <h2 class="beta center">{{ entry.heading }}</h2>
{% endif %}

「メイン画像」と同様に {% if %} タグで実際にテキストがセットされている場合のみ出力するよう分岐しています。なお、行列フィールドと関連フィールドを除き、フィールドの入力値は entry.<フィールドハンドル> で取得できます。

行列フィールドの出力

行列フィールドは、ループ処理してブロックごとに含まれるフィールドを出力する必要があります。最低限必要なコードは、次のようになります。

{# 「記事本文」フィールドのブロックを変数にセット #}
{% set blocks = entry.articleBody %}

必要に応じて、一旦フィールドを変数にセットし

{# ブロックのループ処理 #}
{% for block in blocks.all() %}
  <div class="flex">

    {# block.type.handle の値に応じて switch 文で分岐処理 #}
    {% switch block.type.handle %}
      {# 「新しいセクション」ブロック #}
      {% case 'newSection' %}

      {# 「見出し」ブロック #}
      {% case 'heading' %}

    {% endswitch %}

  </div>
{% endfor %}

{% for %} タグでループ処理を行い、{% switch %} タグでブロックごとにマークアップを定義するための分岐処理を定義しておきます。【参考コミット】

なお、blocks.all() の代わりに、直接 entry.articleBody.all() とすることもできます。

また、「エントリ」や「行列フィールド」などのエレメントを問わず Craft 3 のデフォルトで 100件まで に制限されているため、言葉通りすべてを取得する場合は blocks.limit(null).all() の形で明示的に件数を指定する必要があります。ただし、行列フィールドが100個以上のブロックを持つ場合、管理画面やフロントエンドの表示パフォーマンスの低下に繋がる可能性がありますので注意してください。

ブロックごとのマークアップを定義

それぞれの {% case %} タグ直下に、コーディングデータからコピーしたマークアップを加え、フィールドの出力タグに置き換えていきます。【参考コミット】

{# block.type.handle の値に応じて switch 文で分岐処理 #}
{% switch block.type.handle %}
  {# 「新しいセクション」ブロック #}
  {% case 'newSection' %}
    <hr class="horz-rule">
    <h1 class="beta center">{{ block.sectionHeading }}</h1>

  {# 「見出し」ブロック #}
  {% case 'heading' %}
    <h2 class="delta center subfont caps">{{ block.heading }}</h2>

{% endswitch %}

サンプルコードは {% for block in blocks.all() %} としているため、このループ内であれば block.sectionHeading の形でブロックごとのフィールドを取得できます。

見た目に関するマークアップの調整

あとは、公式デモサイトに見た目を揃えるためのマークアップ調整を行えば完成です。【参考コミット】

この調整については、少し冗長な書き方になっている印象があるため詳細は控えますが、コメント文に解説を加えてありますので参考にしてください。

なお {% macro %} タグについては Twig の公式リファレンスも参照してください。

表示の確認

最後にフロントエンドの表示を確認してみましょう。

エントリ一覧

現時点ではフロントエンドの一覧ページが存在しないため、Craft 3 の管理画面のエントリ一覧にある「地球」アイコンをクリックします。

詳細ページの表示サンプル

公式デモサイトと同様の体裁で、詳細ページが表示できています。

まとめ

今回は、セクション詳細ページ向けのテンプレート作成について見てきました。

レイアウトテンプレートと同様、コーディングデータを流用できれば出力や分岐などの処理を加える程度のため、Twig ベースのテンプレート制作はそれほど難しくなさそうと感じていただけたらと思います。

次回は、引き続き「一覧ページのテンプレート作成」について解説します。