構文
Latte の構文は、ウェブデザイナーの実務上の要求から生まれました。ふつうならかなり厄介な構造をきれいに書ける、最も使いやすい構文を探し求めた結果です。同時に、式はすべて PHP とまったく同じ書き方なので、新しい言語を覚える必要はありません。すでに知っていることをそのまま活かせます。
以下は、タグ、n:属性、コメント、フィルタという基本要素をいくつか示す最小限のテンプレートです。
{* これはコメントです *}
<ul n:if=$items> {* n:if は n:属性です *}
{foreach $items as $item} {* foreach ループを表すタグ *}
<li>{$item|capitalize}</li> {* フィルタを通して変数を出力するタグ *}
{/foreach} {* ループの終わり *}
</ul>
これらの大切な要素と、それがどうやって素晴らしいテンプレートづくりを助けてくれるのかを、もう少し詳しく見ていきましょう。
タグ
テンプレートには、テンプレートのロジックを制御する(foreach
ループなど)タグや、式を出力するタグが含まれます。どちらにも同じ区切り { ... }
を使うので、ほかのシステムと違って、どの場面でどの区切りを使うか考える必要がありません。{
の直後に空白、引用符、もうひとつの { や } が続く場合、Latte
はそれをタグの始まりとみなさないので、JavaScript の構文、JSON、CSS
の規則をテンプレートで問題なく使えます。
すべてのタグの一覧をご覧ください。さらに、独自のカスタムタグを作ることもできます。{ }
の区切りを変えたり、まるごと無効にしたり({syntax double}、{syntax off}、n:syntax
属性を使います)もできます。構文の変更をご覧ください。
Latte は PHP を理解する
タグの中では、見慣れた PHP の式が使えます。
- 変数
- 文字列(HEREDOC と NOWDOC を含む)、配列、数値など
- 演算子
- 関数やメソッドの呼び出し(サンドボックスで制限できます)
- match
- アロー関数
- ファーストクラス callable 構文
- 複数行コメント
/* ... */ - など…
さらに Latte は、いくつかの便利な拡張で PHP の構文を強化しています。
n:属性
{if} … {/if} のように、ひとつの HTML
要素に対して働くペアタグはすべて、n:属性の形に書き換えられます。たとえば冒頭の例の
{foreach} は、次のようにも書けます。
<ul n:if=$items>
<li n:foreach="$items as $item">{$item|capitalize}</li>
</ul>
すると、その機能は属性が置かれた HTML 要素に適用されます。
{var $items = ['I', '♥', 'Latte']}
<p n:foreach="$items as $item">{$item}</p>
出力:
<p>I</p>
<p>♥</p>
<p>Latte</p>
inner-
接頭辞を使うと、要素の内側だけに適用されるように振る舞いを変えられます。
<div n:inner-foreach="$items as $item">
<p>{$item}</p>
<hr>
</div>
出力:
<div>
<p>I</p>
<hr>
<p>♥</p>
<hr>
<p>Latte</p>
<hr>
</div>
tag- 接頭辞を使えば、HTML タグそのものにだけ機能を適用できます。
<p><a href={$url} n:tag-if="$url">タイトル</a></p>
これは変数 $url に応じて次のように出力します。
{* $url が空のとき *}
<p>タイトル</p>
{* $url が 'https://nette.org' のとき *}
<p><a href="https://nette.org">タイトル</a></p>
とはいえ n:属性はペアタグの略記だけではありません。純粋な n:属性もあります。たとえばコーダーの親友 n:class や、とても便利な n:href です。
引用符を使う <div n:if="$foo"> という書き方に加えて、波かっこを使う
<div n:if={$foo}> という書き方もできます。主な利点は、{...}
の中で単引用符と二重引用符の両方を自由に使えることです。
<div n:if={str_contains($val, "foo")}> ... </div>
スマートな HTML 属性
Latte は標準の HTML 属性の扱いを驚くほど簡単にします。checked
のような真偽値属性を面倒みてくれ、null を含む属性を取り除き、class や
style の値を配列で組み立てられるようにします。data- 属性のデータは JSON
に自動でシリアライズまでしてくれます。
{* null は属性を取り除きます *}
<div title={$title}>
{* 真偽値が真偽値属性の有無を制御します *}
<input type="checkbox" checked={$isChecked}>
{* class では配列が使えます *}
<div class={['btn', 'btn-primary', active => $isActive]}>
{* data- 属性では配列が JSON にエンコードされます *}
<div data-config={[theme: dark, version: 2]}>
詳しくは別の章スマートな HTML 属性をご覧ください。
フィルタ
標準フィルタの一覧をご覧ください。
フィルタはパイプ記号のあとに書きます(前に空白があってもかまいません)。
<h1>{$heading|upper}</h1>
フィルタは連ねられ、左から右の順に適用されます。
<h1>{$heading|lower|capitalize}</h1>
引数はフィルタ名のあとにコロンで続け、さらに引数があればカンマで区切ります。かっこを使った呼び出しもできます。
<h1>{$heading|truncate:20,''}</h1>
<h1>{$heading|truncate(20, '')}</h1>
フィルタは式に対しても適用できます。
{var $name = ($title|upper) . ($subtitle|lower)}
ブロックに対しても。
<h1>{block |lower}{$heading}{/block}</h1>
値に直接適用することもできます({=expr}
タグとの組み合わせ)。
<h1>{=' Hello world '|trim}</h1>
値が null になり得て、その場合はフィルタを適用したくないなら、nullsafe フィルタ ?| を使います。
<h1>{$heading?|upper}</h1>
動的 HTML タグ
Latte は動的な HTML タグに対応しています。タグ名に柔軟さが必要なときに便利です。
<h{$level}>見出し</h{$level}>
たとえば上のコードは、変数 $level の値に応じて <h1>見出し</h1> や
<h2>見出し</h2> を生成できます。Latte の動的 HTML
タグは常にペアでなければなりません。代わりの手段は n:tag です。
Latte は安全なテンプレートシステムなので、できあがるタグ名が正しいこと、望ましくない値や悪意ある値を含まないことを確認します。また、終了タグの名前が常に開始タグの名前と一致するようにします。
コメント
コメントは次のように書き、出力には現れません。
{* これは Latte のコメントです *}
タグの中では PHP のコメントが使えます。
{include 'file.info', /* value: 123 */}
空白の制御
Latte
は空白を賢く扱います。読みやすさのために自由にインデントしても、出力はきれいなままです。制御タグが行にひとつだけある場合、その行全体(インデントと改行)が出力から取り除かれます({$var}、{=...}、{_...}
のように出力を行うタグには当てはまらず、そのインデントと末尾の改行は保たれます)。
<ul>
{foreach $items as $item}
<li>{$item}</li>
{/foreach}
</ul>
出力:
<ul>
<li>foo</li>
<li>bar</li>
</ul>
タグが行にひとつだけではなく、ほかの内容と並んでいる場合はどうでしょうか。タグの前の空白は、タグの内側に属します。
<div>
{if $foo}hello{/if}
</div>
インデントは実質的に {if} の内側にあります。$foo
が偽なら何も出力されず、インデントも空行も残りません。$foo
が真なら、出力には自然にインデントが含まれます。整った構造のテンプレートを書くだけで、出力は常にきれいになります。
さらにきれいな出力がほしいときは、Dedent機能を有効にできます。これは {if} や
{foreach} のようなペアタグの入れ子によって生じるインデントも取り除きます。
シンタックスシュガー
引用符のない文字列
単純な文字列では引用符を省けます。
PHP と同じ: {var $arr = ['hello', 'btn--default', '€']}
短縮形: {var $arr = [hello, btn--default, €]}
単純な文字列とは、英字、数字、アンダースコア、ハイフン、ピリオドだけで構成されたものです。数字で始まってはならず、ハイフンで始まったり終わったりしてもいけません。大文字とアンダースコアだけで構成されていると定数(PHP_VERSION
など)とみなされるので、それも避けます。また、次のキーワードと衝突してはいけません:
and、array、clone、default、false、in、instanceof、new、null、or、return、true、xor。
定数
グローバル定数と単純な文字列を区別するには、グローバル名前空間の区切りを使います。
{if \PROJECT_ID === 1} ... {/if}
この書き方は PHP 自体でもまったく正しく、バックスラッシュはその定数がグローバル名前空間にあることを示します。
短縮三項演算子
三項演算子の 3 つめの値が空なら、省略できます。
PHP と同じ: {$stock ? '在庫あり' : ''}
短縮形: {$stock ? '在庫あり'}
配列のキーの現代的な書き方
配列のキーは、関数呼び出しの名前付き引数と同じように書けます。
PHP と同じ: {var $arr = ['one' => 'item 1', 'two' => 'item 2']}
現代的: {var $arr = [one: 'item 1', two: 'item 2']}
フィルタ
フィルタは任意の式に使えます。式全体をかっこで囲むだけです。
{var $content = ($text|truncate: 30|upper)}
in 演算子
in 演算子は in_array() 関数の代わりになります。比較は常に厳密です。
{* in_array($item, $items, true) と同じ *}
{if $item in $items}
...
{/if}
歴史をのぞく窓
Latte はその歴史の中で、数年後に PHP
自体に登場することになるシンタックスシュガーをいくつも先取りしてきました。たとえば Latte
では、PHP で可能になるずっと前から array(1, 2, 3) の代わりに [1, 2, 3]
と書けましたし、nullsafe 演算子 $obj?->foo も使えました。今の PHP の ...$arr
演算子にあたる配列展開演算子 (expand) $arr も、Latte が先に導入したものです。
Latte における PHP の制限
Latte には PHP
の式しか書けません。つまりセミコロンで終わる文は使えません。クラスの宣言もできませんし、if、foreach、switch、return、try、throw
などの制御構造も使えません。それらには Latte
がタグを用意しています。属性、バッククォート、一部のマジック定数も使えません。unset、echo、include、require、exit、eval
も使えません。これらは関数ではなく PHP
の特別な言語構造であり、式ではないからです。コメントは複数行の /* ... */
だけがサポートされます。
とはいえ、RawPhpExtension
拡張を有効にすればこの制限を回避でき、テンプレート作者の責任のもとで {php ...}
タグの中に任意の PHP コードを書けます。