Skip to content

Latest commit

 

History

History
756 lines (517 loc) · 29.9 KB

templates.rst

File metadata and controls

756 lines (517 loc) · 29.9 KB

テンプレートデザイナーのためのTwig

このドキュメントは、テンプレートエンジンの構文や語義について、説明したもので、 Twigテンプレートを作成する方々のリファレンスとして、一番役に立つものになるのではないかと思います。

概要

テンプレートは、単なるテキストファイルです。 テンプレートは、どんなテキストベースの形式 (HTML、 XML, CSV, LaTeX, etc.)でも生成することができます。 また、特に決まった拡張子がないので、.html.xml としても全く問題ありません。

テンプレートには、 変数 が記述されますが、これは、 テンプレートが評価されるときに値に置き換えられるものになります。 また、テンプレートには、タグ も記述され、 タグを使って、テンプレートのロジックをコントロールしていきます。

次の例は、最小構成のテンプレートで、基本的な事項がいくらか盛り込まれたものです。 詳しくは、 追って説明します:

<!DOCTYPE html>
<html>
    <head>
        <title>MYウェブページ</title>
    </head>
    <body>
        <ul id="navigation">
        {% for item in navigation %}
            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
        {% endfor %}
        </ul>

        <h1>MYウェブページ</h1>
        {{ a_variable }}
    </body>
</html>

上のコードの中には、2種類の区切り記号: {% ... %}{{ ... }} がありますが、前者の 区切り記号は、for-ループなどの構文を実行するために使われるもので、後者の区切り記号は、 テンプレートの中で、式の結果を表示するためのものになります。

IDEの統合

数多くのIDEでTwigのシンタックスハイライトと自動補完がサポートされています:

  • Textmate は、Twig bundle でサポートされます
  • Vim は、Jinja syntax plugin でサポートされます
  • Netbeans は、Twig syntax plugin でサポートされます
  • PhpStorm (2.1から、ネイティブにサポート)
  • Eclipse は、 Twig plugin でサポートされます
  • Sublime Text は、 Twig bundle でサポートされます
  • GtkSourceView は、 Twig language definition でサポートされます (geditなどのプロジェクトで使用)
  • CodaSubEthaEdit は、 Twig syntax mode でサポートされます
  • Coda 2 は、 other Twig syntax mode でサポートされます
  • KomodoKomodo Edit は、Djangoのハイライト/構文チェックモードでサポートされます

変数

アプリケーションで、テンプレートに変数を渡すことにより、テンプレートの中で、その変数を取り扱うことができます。 変数は、自身の中に属性や要素を持つこともあり、これにもアクセスすることができます。 変数がどう見えるかは、変数の提供元となるアプリケーションに大きく 左右されます。

変数の属性(PHPオブジェクトのメソッドやプロパティ、あるいは、PHPの配列の要素)にアクセスするには、 ドット (.) を使うか、いわゆる "添え字" 構文 ([]) を使います:

{{ foo.bar }}
{{ foo['bar'] }}

属性に特殊な文字が含まれる場合 (たとえば、- などの文字で、この文字は、マイナス演算子 として解釈されます)、変数の属性には、attribute 関数を代わりに使って アクセスします:

{# foo.data-foo と同じ。foo.data-foo は動作しませんが #}
{{ attribute(foo, 'data-foo') }}

Note

波括弧が変数の一部 ではなく 、printステートメントである ということは、重要です。タグの中で、変数にアクセスする場合は、 変数を括弧で囲まないでください。

変数もしくは属性が存在しない場合についてですが、strict_variables オプションが false にセットされている場合は、 null の値が返ります。 そうでない場合は、Twigによって エラーがスローされます (:ref:`環境オプション<environment_options>` をご覧ください)。

実装

foo.bar とすると、利便性のために、PHPレイヤで次のことが 行われます:

  • foo が配列で、bar が有効な要素であるかチェックします;
  • そうでない場合で、foo がオブジェクトのとき、bar が有効なプロパティであるかチェックします;
  • そうでない場合で、foo がオブジェクトのとき、bar が有効なメソッドであるかチェックします; (たとえ、bar がコンストラクタであっても有効であると判断されます - コンストラクタには、__construct() を代わりに使用してください);
  • そうでない場合で、foo がオブジェクトのとき、getBar が有効なメソッドであるかチェックします;
  • そうでない場合で、foo がオブジェクトのとき、isBar が有効なメソッドであるかチェックします;
  • そうでない場合、null の値を返します。

一方、foo['bar'] は、PHPの配列に対してのみ動作します:

  • foo が配列で、bar が有効な要素であるかチェックします;
  • そうでない場合、null の値を返します。

Note

変数の動的属性を取得したい場合は、 :doc:`attribute<functions/attribute>` 関数を使用してください。

グローバル変数

次の変数は、テンプレートの中でいつでも利用することができます:

  • _self: 現在のテンプレートを参照します;
  • _context: 現在のコンテキストを参照します;
  • _charset: 現在の文字セットを参照します。

変数への代入

コードブロックの中で、変数には、値を代入することができます。 代入するには、 :doc:`set<tags/set>` タグを使用します:

{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}

フィルタ

変数は、フィルタ で値を修正することができます。 フィルタは、パイプ記号 (|) で 変数と分けられ、場合によっては、丸括弧使って追加の引数が指定されます。 フィルタを複数連続して呼び出すこともでき、このとき、あるフィルタの出力は、 次のフィルタに適用されます。

次の例では、name から、すべてのHTMLタグが除去され、タイトルケース(先頭文字が大文字で残りが小文字) に変換されます:

{{ name|striptags|title }}

フィルタは、引数を丸括弧で囲んで受け取ることができます。 この例では、listをカンマで連結しています:

{{ list|join(', ') }}

コードの領域にフィルタを適用するには、その領域を :doc:`filter<tags/filter>` タグで囲みます:

{% filter upper %}
  このテキストは、全部大文字になります
{% endfilter %}

組み込みのフィルタについて、さらに詳しく知るには、:doc:`フィルタ<filters/index>` のページを ご覧ください。

関数

関数は、内容を生成するために、呼び出すことができます。関数は、 小括弧 (()) が後に続く名前で呼び出され、引数をとることもあります。

例えば、range 関数は、整数の等差数列で構成される リストを返します:

{% for i in range(0, 3) %}
    {{ i }},
{% endfor %}

組み込みの関数について、さらに詳しく知るには、:doc:`関数<functions/index>` のページを ご覧ください。

制御構文

制御構文は、プログラムのフローを制御する、あらゆるものを 表すものです - 条件 (i.e. if/elseif/else), for-ループ, ブロック のようなものも含まれます。 制御構文は、{% ... %} の中に 記述されます。

例えば、users という変数により与えられたユーザーのリストを 表示するには、:doc:`for<tags/for>` タグを使用します:

<h1>メンバー</h1>
<ul>
    {% for user in users %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>

:doc:`if<tags/if>` タグは、式を検査するのに使用することができます:

{% if users|length > 0 %}
    <ul>
        {% for user in users %}
            <li>{{ user.username|e }}</li>
        {% endfor %}
    </ul>
{% endif %}

組み込みのタグについて、さらに詳しく知るには、:doc:`タグ<tags/index>` のページをご覧ください。

コメント

テンプレートの一部の行をコメントアウトするには、コメント構文 {# ...#} を使います。これは、デバッグのために役立ち、他のテンプレートデザイナー、あるいは自分自身のために情報を追加する ためにも使えるものです:

{# note: これはもう使っていないので、テンプレートを無効化しています
    {% for user in users %}
        ...
    {% endfor %}
#}

他のテンプレートのインクルード

:doc:`include<tags/include>` タグは、テンプレートをインクルードし、 そのテンプレートのレンダリング結果の内容を現在のテンプレートの中で返すために使えます:

{% include 'sidebar.html' %}

デフォルトでは、インクルードされたテンプレートには、現在のコンテキストが渡されます。

インクルードされたテンプレートに渡されるコンテキストには、親のテンプレートで定義された 変数が入っています:

{% for box in boxes %}
    {% include "render_box.html" %}
{% endfor %}

このインクルードされたテンプレート render_box.html では、box にアクセスすることができるというわけです。

上のテンプレートのファイル名のところは、テンプレートのローダーによって変わります。 例えば、 Twig_Loader_Filesystem では、ファイル名を指定すれば、別のテンプレートにアクセスする ことができます。 サブディレクトリのテンプレートには、スラッシュを使ってアクセスできます:

{% include "sections/articles/sidebar.html" %}

この振る舞いは、Twigを組み込んでいるアプリケーションによって変わります。

テンプレートの継承

Twig の最も強力なところといえば、テンプレート継承です。 テンプレート継承を使えば、 基本になる "骨組みの" テンプレートを構築でき、このテンプレートに、サイトの共通要素を すべて入れて、子テンプレートでオーバーライドできる ブロック を定義 しておくことができます。

難しく聞こえるかもしれませんが、非常に簡単です。 一つの例から始めるのが、 これを理解する近道です。

基本になるテンプレート base.html を定義してみましょう。 このテンプレートでは、単純な2カラム構成のページとして使えるもので、 簡単なHTMLの骨組みのドキュメントが定義されています:

<!DOCTYPE html>
<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css" />
            <title>{% block title %}{% endblock %} - MYウェブページ</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>

この例では、:doc:`block<tags/block>` タグで、4つのブロックが定義されていますが、 このブロックの内容は、子テンプレートで埋めることができます。 block タグが行うことのすべては、 テンプレートエンジンに、子テンプレートが、各部分をオーバーライドできるのだということを 教えるだけなのです。

子テンプレートは、大体このようになっています:

{% extends "base.html" %}

{% block title %}Index{% endblock %}
{% block head %}
    {{ parent() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Index</h1>
    <p class="important">
        素晴らしいホームページへようこそ。
    </p>
{% endblock %}

:doc:`extends<tags/extends>` タグがここでのキーです。 extendsタグは、テンプレートエンジンに、 このテンプレートは、別のテンプレートを"extends (継承/拡張)" しているのだと伝えるものです。テンプレートシステムが、 このテンプレートを評価するときには、まず、親の場所を特定します。 extendsタグは、 テンプレートの最初のタグでなければならないというわけです。

ここでは、子テンプレートで、footer ブロックを定義していないので、 親テンプレートの値が代わりに使用されているのにご注意ください。

:doc:`parent<functions/parent>` 関数を使えば、親ブロックの内容を レンダリングすることもできます。 この関数により、親ブロックの処理結果が 返されます:

{% block sidebar %}
    <h3>目次</h3>
    ...
    {{ parent() }}
{% endblock %}

Tip

:doc:`extends<tags/extends>` タグのドキュメントのページでは、さらに高度な 機能が解説されています。 例えば、ブロックのネスト、スコープ、動的継承、それから 条件付き継承などといったものが解説されています。

Note

Twigでは、いわゆる、水平方向の再利用(horizontal reuse)により、多重継承もサポートされています。 :doc:`use<tags/use>` タグにより、これが利用可能です。この機能は、高度な機能で、 通常のテンプレートで必要とされることはほとんどありません。

HTML エスケープ

テンプレートからHTMLを生成する際には、変数に含まれる文字が、 結果のHTMLに影響を与えるリスクが常にあります。 これに対しては、 2つのアプローチがあります: 変数をそれぞれ手動でエスケープする方法、 あるいは、デフォルトですべて自動でエスケープする方法です。

Twigでは、両方とも利用でき、デフォルトでは、自動エスケープが有効になっています。

Note

自動エスケープは escaper エクステンションが有効になっている (デフォルトでは有効になっています) 場合にのみ利用可能です。

手動でのエスケープを利用する

手動でのエスケープが有効な場合、必要に応じて、変数をエスケープするのは、あなたの 責任になります。 何をエスケープすればよいのでしょうか? 信頼できない変数はすべてです。

エスケープは、:doc:`escape<filters/escape>` または e フィルタを通じて、 パイプされて処理されます:

{{ user.username|e }}

デフォルトでは、escape フィルタでは、html ストラテジが使われますが、これは、エスケープのコンテキスト によって異なります。他に利用可能なストラテジを明示的に使うことも できます:

{{ user.username|e('js') }} {{ user.username|e('css') }} {{ user.username|e('url') }} {{ user.username|e('html_attr') }}

自動でのエスケープを利用する

自動エスケープが有効になっているか否かにかかわらず、テンプレートの領域を :doc:`autoescape<tags/autoescape>` タグを使ってマークし、エスケープすべきか否かを 指定します:

{% autoescape %}
    このブロックの中は何でも(HTMLストラテジを使って)自動でエスケープされます。
{% endautoescape %}

デフォルトでは、自動エスケープでは、html ストラテジが使用されます。 変数を 他のコンテキストで出力したいときは、適切なエスケープストラテジで、 明示的にエスケープする必要があります:

{% autoescape 'js' %}
    このブロックの中は何でも(JSストラテジを使って)自動でエスケープされます。
{% endautoescape %}

エスケープ

Twigで、ある部分を変数やブロックとして取り扱いつつも、その部分をTwigで無視することが望ましいか、 あるいは無視することが必要になる場面も時々あります。 たとえば、デフォルトの構文が使用されている場合で、 {{ をテンプレートの中で生の文字列として使用したい場合、これが変数の開始記号とならないように、 ちょっとしたトリックを使う必要があります。

一番簡単な方法は、変数の式を用いて、変数区切り文字 ({{) を 出力するというものです:

{{ '{{' }}

もっと大きな領域に対しては、 :doc:`raw<tags/raw>` で、ブロックをマークする方がよいでしょう。

マクロ

マクロは、通常のプログラム言語の関数と比較対比されるものです。 マクロは、 頻繁に使われるHTMLの一部を再利用するために使うことができ、これにより、繰り返しの記述を避けることができます。

マクロは、:doc:`macro<tags/macro>` タグを使って定義します。 次は、マクロの簡単な例で(あとで、 forms.html という名前で出てきます)、form 要素をレンダリングする例になります:

{% macro input(name, value, type, size) %}
    <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}

マクロは、どんなテンプレートの中でも定義でき、使う前には、:doc:`import<tags/import>` タグで、 これを "インポート"する必要があります:

{% import "forms.html" as forms %}

<p>{{ forms.input('username') }}</p>

別のやり方として、マクロをそれぞれインポートすることもでき、:doc:`from<tags/from>` タグを使って、現在の名前空間に、 テンプレートから名前をインポートし、加えて、任意で別名をつけることもできます:

{% from 'forms.html' import input as input_field %}

<dl>
    <dt>ユーザー名</dt>
    <dd>{{ input_field('username') }}</dd>
    <dt>パスワード</dt>
    <dd>{{ input_field('password', '', 'password') }}</dd>
</dl>

Twigでは、どこでも式を使えます。 式は、通常のPHPと非常に似通った動作になっており、 PHPを使っていないくても、簡単に感じるに違いありません。

Note

演算子の優先順位は次の通りで、優先順位が低い演算子が最初の方に リストアップされています: b-and, b-xor, b-or, or, and, ==, !=, <, >, >=, <=, in, .., +, -, ~, *, /, //, %, is, **.

リテラル

.. versionadded:: 1.5
    Twig 1.5で、ハッシュのキーをキー名とすることができるようになり、そのための式が追加されました。

式のもっとも単純な形は、リテラルです。 リテラルとは、 文字列, 数値, そして 配列といったPHPの型を表すものです。 次のリテラル があります:

  • "Hello World": ダブルクォーテーションまたは、シングルクォーテーションに囲まれたものは、 いずれも文字列です。これは、テンプレートで文字列が必要となった時に (たとえば、 関数呼び出し、フィルタの引数として、あるいは、テンプレートの拡張やインクルードの 引数としてなどに)、いつでも使えます。

  • 42 / 42.23: 整数と浮動小数点は、単に 数字をそこに記述するだけです。 小数点が一つある場合は、浮動小数点に、 ひとつもなければ、整数になります。

  • ["foo", "bar"]: 配列は、カンマ(,)区切りの連続した式として定義し、 角括弧で囲みます。

  • {"foo": "bar"}: ハッシュは、カンマ(,)区切りで、キーと値のリストとして 定義し、波括弧で囲みます:

    {# キーを文字列として #}
    { 'foo': 'foo', 'bar': 'bar' }
    
    {# キーをキー名として (上のハッシュと同じもの) -- Twig 1.5 より #}
    { foo: 'foo', bar: 'bar' }
    
    {# キーを整数として #}
    { 2: 'foo', 4: 'bar' }
    
    {# キーを式として (式は、丸括弧の中に入れる必要があります) -- Twig 1.5 より #}
    { (1 + 1): 'foo', (a ~ 'b'): 'bar' }
  • true / false: true は、真の値を表し、 false は、偽の値を表します。

  • null: null は、特定の値を表しません。この値は、 変数が存在しない場合に返されます。 none は、 null の別名です。

配列とハッシュは、ネストすることができます:

{% set foo = [1, {"foo": "bar"}] %}

数値演算

Twigでは値の計算が可能です。 テンプレートでは、めったに役に立たないかもしれませんが、 機能を網羅するために用意されています。 次の演算子がサポートされています:

  • +: 2つの対象を加算します (演算対象は、数字にキャストされます)。 {{ 1 + 1 }}2
  • -: 最初の数から、2番目の数を減算します。 {{ 3 - 2 }}1
  • /: 2つの数字を除算します。 戻り値は、浮動小数点の 数値になります。 {{ 1 / 2 }}{{ 0.5 }}
  • %: 整数で除算した余りを計算します。 {{ 11 % 7 }}4
  • //: 2つの数字を除算し、結果を切り捨てて整数にして返します。 {{ 20 // 7 }}2
  • *: 左の演算対象を右の演算対象で、乗算します。 {{ 2 * 2 }} は、 4 を返します。
  • **: 左の演算対象を右の演算対象で、累乗します。 {{ 2 ** 3 }} は、 8 を返します。

論理演算

複数の式を次の演算子で繋げることができます:

  • and: 左右の値が、どちらもtrueの場合に、trueを返します。
  • or: 左右の値が、どちらか一方、trueの場合に、trueを返します。
  • not: ステートメントを否定します。
  • (expr): 式をグループ化します。

Note

Twig では、ビット演算子 (b-and, b-xor, b-or) もサポートされています。

比較演算

次の比較演算子が、あらゆる式でサポートされています: ==, !=, <, >, >=, <=.

包含演算子

in 演算子は、含まれるかどうかを検査します。

左が、右の中に含まれる場合は、 true を返します:

{# true を返す #}

{{ 1 in [1, 2, 3] }}

{{ 'cd' in 'abcde' }}

Tip

このフィルタを使えば、文字列、配列、 あるいは Traversable インターフェースを実装したオブジェクトの中に、値が含まれるかどうか検査することができます。

not in 演算子を使って、否定のテストができます:

{% if 1 not in [1, 2, 3] %}

{# 下記と同じ #}
{% if not (1 in [1, 2, 3]) %}

テスト演算子

is 演算子は、テストを行います。 テストは、変数に対して、 一般の式が当てはまるかテストするために使われます。 右がテストの名前になります:

{# 変数が奇数がどうかを調べます #}

{{ name is odd }}

テストは、引数を取ることもできます:

{% if loop.index is divisibleby(3) %}

is not 演算子を使って、否定のテストができます:

{% if loop.index is not divisibleby(3) %}

{# 下記と同じ #}
{% if not (loop.index is divisibleby(3)) %}

組込みのテストについて、さらに詳しく知るには、 :doc:`tests<tests/index>` ページを ご覧ください。

その他の演算子

次の演算子は、非常に有用ですが、他のどのカテゴリにも 属さないものです:

  • ..: 演算子の前後の値に基づいて、連続した値を生成します
    (これは、 :doc:`range<functions/range>` 関数のシンタックスシュガーになります)。
  • |: フィルタを適用します。
  • ~: 値をすべて文字列に変換して連結します。 {{ "Hello " ~ name ~ "!" }} は、 ( name'John' だとすると、) Hello John! を返します。
  • ., []: オブジェクトの属性を取得します。
  • ?:: PHPの3項演算子: {{ foo ? 'yes' : 'no' }}

文字列への埋め込み演算

.. versionadded:: 1.5
    文字列への埋め込み演算は、Twig 1.5 で追加されました。

文字列への埋め込み演算 (#{expression}) を使えば、有効な式であれば、どんなものでも、文字列の中で使用することが できます。 式の評価の結果が、文字列の中に差し込まれ ます:

{{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}

空白文字のコントロール

.. versionadded:: 1.1
    タグレベルでの空白文字のコントロールは、Twig 1.1 で追加されました。

テンプレートタグの最初の改行は、(PHPのように)自動で除去されます。 空白文字は、それ以上は、テンプレートエンジンで変更されることはありません。ですから、各空白文字 (スペース、タブ、改行など) は、変更されずに返されます。

spaceless タグを使うと、 HTML タグの間の 空白文字が除去されます:

{% spaceless %}
    <div>
        <strong>foo</strong>
    </div>
{% endspaceless %}

{# 出力は、<div><strong>foo</strong></div> となります #}

spaceless タグの他に、タグひとつひとつのレベルで、空白文字をコントロール することもできます。 タグで、空白文字コントロール修飾子を使えば、 前後の空白文字をトリミングできます:

{% set value = 'no spaces' %}
{#- 前後の空白文字を取ります -#}
{%- if true -%}
    {{- value -}}
{%- endif -%}

{# 'no spaces' が出力されます #}

上の例では、デフォルトの、空白文字コントロール修飾子が使われており、どうやって、 タグの周りの空白文字を除去するかが示されています。 スペースのトリミングは、 タグのサイドにある空白文字を全部除去します。 タグの一方のサイドだけ空白文字をトリミングすることも できます:

{% set value = 'no spaces' %}
<li>    {{- value }}    </li>

{# '<li>no spaces    </li>' と出力 #}

エクステンション

Twigは、簡単に拡張可能です。

新しいタグ、フィルタ、関数などをお探しでしたら、Twig 公式の エクステンション・リポジトリ を ご覧ください。

独自のエクステンションを作成したい場合は、 :ref:`エクステンションの 作成<creating_extensions>` の章をお読みください。