校正オプション(フィルター)


Twigの記法では、変数の中にパイプ(|)で区切りフィルターを指定します {{ 変数|フィルター1|フィルター2 }}Twig標準の仕様に従います)

{% set content = '今日の天気は\n晴れです' %}

<p>{{ content|nl2br|safe_html }}</p>

使用できる校正オプションの種類

  • 従来の標準校正オプション

  • Hook.php で拡張した校正オプション

  • Twig標準のフィルター

従来の標準校正オプションは利用できますが、Twig標準のフィルターと名前がかぶるものもあります。この場合Twigのフィルターが優先されるので、従来の標準校正オプションを指定したい場合は、プレフィックス acms_ を付与して指定ください。

名前が校正オプション・フィルター例

date escape nl2br trim number_format split など

従来の校正オプションを使用する

{{ entry.datetime|acms_date('Y年m月d日') }}

従来のa-blog cmsの校正オプションに加え、Twig標準のフィルターも全く同じ記法で指定することができます。

{% set sizes = [34, 36, 38, 40, 42] %}

{{ sizes|filter(v => v > 38)|join(', ') }}
{# output 40, 42 #}

引数に変数を指定

従来の校正オプションでは、一部校正オプションのみ引数に変数を利用できましたが、Twig記法だと全てのフィルターに変数が利用できます

{% set content = '文書を途中で切ります' %}
{% set length = 4 %}
{% set ellipsis = '...' %}

<p>
  {{ content|mb_trim(length, ellipsis) }}
</p>

フィルターを使用したデフォルト値

変数の値がなかった場合に、デフォルト値を出力することができます。

<p>{{ nickname | default("ゲスト") }}</p>

twigでの「raw」校正オプション(フィルター)の仕様が変更になります。

既存テンプレート
{hoge}[raw]
危険なタグはエスケープされ、安全なHTMLは出力されます

{hoge}[raw|allow_dangerous_tag]
scriptを含めエスケープを無効にして、値をそのまま出力します。使用箇所には注意が必要です。

Twigテンプレート
{{ hoge|safe_html }}
危険なタグはエスケープされ、安全なHTMLは出力されます。

{{ hoge|raw }}
scriptを含めエスケープを無効にして、値をそのまま出力します。使用箇所には注意が必要です。

インクルードの書き方


Twigでのインクルードの書き方について解説します。(Twig標準の仕様に従います)

基本的なインクルード

include関数を使ってテンプレートをインクルードします。

{{ include('/path/to/parts.twig') }}

変数を渡す

インクルードするテンプレートに変数を渡したい場合は、第2引数として変数を渡します

{{ include('/path/to/parts.twig', { title: 'タイトルです' }) }}

このように書くことで、/path/to/parts.twig 内で title 変数が使えるようになります。

ファイルが存在しない場合のエラー回避

従来のインクルード文だと、インクルードするファイルがない場合でもエラーは発生しませんでしたが、Twigのインクルードはファイルが存在しない場合エラーが出力されます。

インクルードするファイルが存在しない場合にエラーを回避するには、第3引数にtrueを渡してignore_missingオプションを有効にします。

{{ include(/path/to/parts.twig', {}, true) }}
or
{{ include('/path/to/parts.twig', {}, ignore_missing = true) }}

インクルード文の中にはグローバル変数以外にも全ての変数が利用できます。

従来のインクルードだと、インクルードパス内に利用できる変数はグローバル変数かつ特定のものに制限されていましたが、Twigのインクルードはすべての変数をインクルードパスに含めることが可能です。

{% set filename = 'hoge' %}

{{ include('/include/' ~ filename ~ '.twig', ignore_missing = true) }}

Twig記法と従来記法の併用について


Twigが有効なテーマでは、Twig記法と従来のテンプレート記法を混在させて記述できます。
ただし、テンプレートの解決順により、特定の組み合わせでは記法が正しく反映されない場合があります。

テンプレートの解決順

Twigが有効な場合、テンプレートは以下の順序で解決されます。

  1. Twigによる記述の解決
    {% include %}{% extends %} など、Twigの構文を含む部分が先に処理されます)

  2. Twigが解決された後に、従来のテンプレート記法が解決される
    @include@extends など、従来の構文が後から処理されます)

このため、処理順の都合で、テンプレートが正しく解決されないパターンがあります。

テンプレートが解決されないパターン

  • 従来の @include で読み込んだテンプレートにあるTwig記法は解決されない

  • 従来の @extends で継承したテンプレート以下にあるTwig記法は解決されない

  • 従来の @extends で継承されているテンプレートは、Twig記法でインクルード出来ない


簡単に整理すると、Twigが先に解決されるため、従来記法によるインクルードやテンプレート継承されたテンプレートでは、Twig記法は使えないということになります。逆にいうとルートテンプレートからTwigによるテンプレート継承や、インクルードがされていれば、従来記法と併用が可能です。

Twigテンプレートの拡張子


拡張子は「twig」がおすすめ

Twigテンプレートには特に拡張子の制限はありません。
そのため、拡張子が .html のテンプレートファイルにTwigの記法を使っても、正しく動作します。

しかし、Twigで記述する場合は .twig 拡張子を使用することをおすすめします
理由は、エディタがテンプレートをTwigとして認識し、構文ハイライトやコード補完、Twig専用のフォーマット機能など、開発を効率化する機能を利用できるためです。

ファイル例

_top.twig
index.twig
_entry.twig

URLでテンプレートを指定する場合の注意点

通常、動的テンプレートやインクルード用テンプレートでは、ファイル名をURLで直接指定することはありません。
しかし、ページURLとテンプレートファイル名を合わせたい場合には注意が必要です。

例として、検索結果ページを

https://example.com/search.html

で表示したい場合、テンプレートファイルを search.twig にすると、URLが

https://example.com/search.twig

になってしまいます。

これを避けるには、テンプレートファイル名を search.html.twig にします。
URLと一致する .html 部分を含めたファイル名にすることで、URLを変更せずにTwigテンプレートを利用できます。

URLで指定されたファイル名に対して自動的に .twig 拡張子を持つテンプレートも検索する仕組みがあるため、search.html.twig でも正しく読み込まれます。

その他のTwig機能について


a-blog cms での Twig の基本的な使い方について学んできましたが、他にも便利なTwigの機能がありますので、ぜひ目を通してみてください。

Twigのドキュメント

以下一部便利な機能を紹介します。

macro(マクロ)機能

Twigには、テンプレート内で関数のように使える macro(マクロ)機能 があります。
複雑なHTML構造や繰り返し処理をひとつの関数としてまとめられるため、特に階層構造のデータを扱うときに便利です。

階層データの例

たとえば「V2_Category_Tree」モジュールは、カテゴリが入れ子になった階層構造のデータを返します。

{
  categories:
    [
      {
        id: 1,
        name: "お知らせ",
      },
      {
        id: 2,
        name: "製品",
        children:
          [
            {
              id: 3,
              name: "家庭用製品",
            },
            {
              id: 4,
              name: "業務用製品",
              children:
                [
                  {
                    id: 6,
                    name: "業務用製品のお知らせ",
                  },
                ],
            },
          ],
      },
    ]
}

for文のみで書く場合

階層をすべて表示しようとすると、階層分だけfor文をネストする必要があり、コードが深く複雑になります。

{% set tree = module('V2_Category_Tree') %}

<ul>
  {% for category in tree.categories %}
    <li>
      {{ category.name }}
      {% if category.children is not empty %}
        <ul>
          {% for child in category.children %}
            <li>
              {{ child.name }}
              {% if child.children is not empty %}
                <ul>
                  {% for child2 in child.children %}
                    <li>{{ child2.name }}</li>
                  {% endfor %}
                </ul>
              {% endif %}
            </li>
          {% endfor %}
        </ul>
      {% endif %}
    </li>
  {% endfor %}
</ul>

macroを使ってシンプルに書く

macroを使えば、階層構造の処理を再帰的に呼び出せる関数としてまとめられるため、コードがすっきりします。

{% set tree = module('V2_Category_Tree') %}

{% macro renderCategories(categories) %}
  <ul>
    {% for category in categories %}
      <li>
        {{ category.name }}
        {% if category.children is not empty %}
          {{ _self.renderCategories(category.children) }}
        {% endif %}
      </li>
    {% endfor %}
  </ul>
{% endmacro %}

{{ _self.renderCategories(tree.categories) }}
  • macroはテンプレート内で定義できる関数のような構文

  • 上記例ではrenderCategoriesというマクロを作成し、カテゴリをリスト表示。

  • 子カテゴリ(children)が存在すれば同じマクロを再帰的に呼び出し、階層の深さに制限なく対応可能。

  • 呼び出しは_self.マクロ名()で行います。

Twig記法をそのまま出力する

{{ ... }}{% ... %} など、テンプレートとして解釈されてほしくない場合は verbatim タグを使用することで、そのまま出力することができます。

たとえば、他のテンプレートエンジン(Vue.js や Angular など)と併用し、{{ }} がTwigに解釈されないようにしたい場合などに便利です。

{% verbatim %}
  {{ message }}
  {% if user %}
    Hello, {{ user }}!
  {% endif %}
{% endverbatim %}