このドキュメントは、テンプレートエンジンの構文や語義について、説明したもので、 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で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などのプロジェクトで使用)
- Coda と SubEthaEdit は、 Twig syntax mode でサポートされます
- Coda 2 は、 other Twig syntax mode でサポートされます
- Komodo と Komodo 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 %}
© 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に影響を与えるリスクが常にあります。 これに対しては、 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>` の章をお読みください。