Craft CMS のテンプレートについて理解しよう(ベーステンプレート編)

これは Craft CMS Advent Calendar 2016 12日目の記事です。

今回は、実際にベーステンプレートを作成しながら、テンプレートの書き方を見ていきます。
JeKyll をはじめとする静的サイトジェネレータをお使いの方であれば、コーディングデータとの連携が容易なことを実感いただけると思います。

テンプレートファイルの構成

ここで作成するテンプレートファイルの構成を下記とします。
_layout_bootstrap.twig は全体のレイアウト、_parcials 下層のファイルはインクルードパーツ、blog 下層には以前作成した ブログ セクションのエントリを表示する想定です。

それぞれのディレクトリや空のファイルをあらかじめ作成しておきます。

craft/templates
├── _parcials/
│   ├── header.twig
│   └── footer.twig
├── _layout_bootstrap.twig
└── blog/
    ├── _entry.twig
    └── index.twig

Happy Leager のテンプレートと混同しないよう拡張子を .twig としますが、お好みで .html.php にしてください。

_layout_bootstrap.twig の編集

ベースレイアウトとなる _layout_bootstrap.twig には、下記コードを入力してください。

{#
 # レイアウト:BootStrap
 # -----------------
 #
 # BootStrap v3.x をベースとするベーステンプレート。
-#}

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{ siteName }}</title>

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
  {{ getHeadHtml() }}
</head>
<body>
  {# 共通ヘッダーの読込 #}
  {% include '_parcials/header' %}

  {# mainContent ブロックを定義 #}
  {% block mainContent %}
    <div class="container">
      <p>ここにメインコンテンツを表示します。</p>
    </div>
  {% endblock %}

  {# 共通フッターの読込 #}
  {% include '_parcials/footer' %}

  <script src="http://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
  {{ getFootHtml() }}
</body>
</html>

いくつかコードを抜き出して、ポイントをまとめてみます。

変数の出力

<title>{{ siteName }}</title>

{{ siteName }} には、管理画面の 設定 > 一般 > サイト名 に入力された内容が出力されます。

スタイル定義や CSS ファイルの読み込みを追加

{{ getHeadHtml() }}

テンプレートごとに {% includeCss %} (style タグの中身をセット)、または、 {% includeCssFile %} (link タグによる CSS ファイルの読み込み)でセットされた内容をここに出力します。

共通テンプレートの読み込み

{% include '_parcials/header' %}

記述された位置で、共通テンプレートを読み込みます。
craft/templates 以下のファイルパスを拡張子を除いた形で指定します。

継承先で上書きするためのブロック定義

{% block mainContent %}
  <div class="container">
    <p>ここにメインコンテンツを表示します。</p>
  </div>
{% endblock %}

継承先のテンプレートで上書きを可能にする箇所を {% block %} タグでセットします。
mainContent はこのブロックの名称です。この名称が一意であれば、テンプレート内に複数のブロックを定義することが可能です。

script タグや JS ファイルの読み込みを追加

{{ getFootHtml() }}

テンプレートごとに {% includeJs %} (script タグの中身をセット)、または、 {% includeJsFile %} (script タグによる JS ファイルの読み込み)でセットされた内容をここに出力します。

_parcials/header.twig の編集

共通ヘッダーのマークアップを _parcials/header.twig に記述します。

<nav class="navbar navbar-inverse navbar-fixed-top">
  <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="{{ siteUrl }}">{{ siteName }}</a>
    </div>
    <div id="navbar" class="collapse navbar-collapse">
      <ul class="nav navbar-nav navbar-right">
        <li class="active"><a href="{{ siteUrl }}">Home</a></li>
        <li><a href="{{ siteUrl }}about/">About Us</a></li>
        <li><a href="{{ siteUrl }}services/">Services</a></li>
        <li><a href="{{ siteUrl }}work/">Our Work</a></li>
        <li><a href="{{ siteUrl }}news/">News</a></li>
        <li><a href="{{ siteUrl }}blog/">Blog</a></li>
      </ul>
    </div><!--/.nav-collapse -->
  </div>
</nav>

Bootstrap v3 向けの一般的なコードとなりますが

<a class="navbar-brand" href="{{ siteUrl }}">{{ siteName }}</a>

一部、サイト名とサイト URL を変数から出力する形にしています。

_parcials/footer.twig の編集

共通フッターのマークアップを _parcials/footer.twig に記述します。
こちらも、シンプルなマークアップです。

<footer id="footer">
  <hr>
  <div class="container">
    <div class="col-md-8">
      <a href="mailto:{{ footer.email }}">{{ footer.email }}</a>
    </div>
    <div class="col-md-4">
      <p class="muted pull-right">{{ footer.copyrightNotice|replace('{year}', now|date('Y')) }}</p>
    </div>
  </div>
</footer>

グローバルの入力内容を取得

<a href="mailto:{{ footer.email }}">{{ footer.email }}</a>

管理画面の グローバル で入力された内容は、 {グローバルセットのハンドル}.{フィールドのハンドル} の形で取得できます。

ここでは {{ footer.email }} とし、グローバル > Footer Content > メール の値を出力しています。

blog/index.twig の編集

最後に、ブログの一覧ページのテンプレート blog/index.twig を記述します。

{#
 # ブログ:インデックス テンプレート
 # -----------------
 #
 # 「ブログ」セクションの一覧ページ用テンプレート。
-#}

{# ベーステンプレートとして _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 &raquo;</a></p>
    </div>
  </div>
  <div class="container">
    <p>blog/index.twig の mainContent で上書き</p>
  </div>
{% endblock %}

ベースレイアウトの継承

{% extends '_layout_bootstrap' %}

ベースとなるテンプレートを読み込みます。
{% include %} と同様に craft/templates 以下のファイルパスを拡張子を除いた形で指定します。

テンプレート固有のスタイル定義を追加

{% set blogCss %}
  body {
    padding-top: 50px;
  }
{% endset %}

{% includeCss blogCss %}

複数行に渡るため、一旦 {% set %} で変数名 blogCss にスタイル定義をセットします。
続けて {% includeCss %} でこのテンプレートで CSS を出力しています。

ブロックの上書き

{% 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 &raquo;</a></p>
    </div>
  </div>
  <div class="container">
    <p>blog/index.twig の mainContent で上書き</p>
  </div>
{% endblock %}

mainContent ブロックを任意の内容で上書きします。

{% extends %} を記述したテンプレートでは、 {% block %} に内包されていない出力関連のタグがあるとテンプレートエラーになりますので、注意しましょう。

表示の確認

ここまで調整したら、ブラウザでアクセスして表示を確認してみましょう。
http://localhost/blog/index

blog/index の表示結果

ベースレイアウトや共通パーツなどを利用しつつ、 mainContent ブロックを上書きできていることが判りますね。

<style type="text/css">
  body {
    padding-top: 50px;
  }
</style>

ソースコードを見ると、 </head> 直前に指定したスタイル定義を追加できています。

まとめ

ここでは、実際にベーステンプレートを用意し、そこで使用したタグについて解説してみました。
条件分岐などには触れていませんが、基本的なテンプレートの書き方は理解いただけたかと思います。

次回は、エントリの一覧用テンプレートを題材に、もう少し掘り下げてみます。