開発プラクティス
インストール
Latte をインストールする最良の方法は Composer を使用することです:
composer require latte/latte
サポートされている PHP バージョン(最新のマイナーバージョンの Latte に適用):
バージョン | PHP との互換性 |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
テンプレートをレンダリングする方法
テンプレートをレンダリングするにはどうすればよいですか?この簡単なコードで十分です:
$latte = new Latte\Engine;
// キャッシュディレクトリ
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* テンプレート変数 */ ];
// または $params = new TemplateParameters(/* ... */);
// 出力にレンダリング
$latte->render('template.latte', $params);
// 変数にレンダリング
$output = $latte->renderToString('template.latte', $params);
パラメータは配列、またはオブジェクトである方が望ましいです。これにより、型チェックとエディタでの補完が保証されます。
使用例は Latte examples リポジトリにもあります。
パフォーマンスとキャッシュ
Latte のテンプレートは非常に高速です。Latte はそれらを直接 PHP コードにコンパイルし、ディスク上のキャッシュに保存します。したがって、純粋な PHP で書かれたテンプレートと比較して追加のオーバーヘッドはありません。
ソースファイルを変更するたびに、キャッシュは自動的に再生成されます。したがって、開発中は Latte テンプレートを快適に編集し、変更をすぐにブラウザで確認できます。この機能は本番環境で無効にして、パフォーマンスを少し節約できます:
$latte->setAutoRefresh(false);
本番サーバーにデプロイする場合、特に大規模なアプリケーションでは、最初のキャッシュ生成に少し時間がかかることがあります。Latte には「キャッシュスタンピード」に対する組み込みの防止策があります:https://en.wikipedia.org/wiki/Cache_stampede。 これは、Latte を起動する多数の同時リクエストが発生し、キャッシュがまだ存在しないため、すべてが同時に生成を開始する状況です。これにより、サーバーに過度の負荷がかかります。 Latte は賢く、複数の同時リクエストがある場合、最初のスレッドのみがキャッシュを生成し、他のスレッドは待機して後でそれを使用します。
クラスとしてのパラメータ
テンプレートに変数を配列として渡すよりも、クラスを作成する方が良いです。型安全な記述、IDEでの快適な補完、およびフィルタや関数を登録するためのパスが得られます。
class MailTemplateParameters
{
public function __construct(
public string $lang,
public Address $address,
public string $subject,
public array $items,
public ?float $price = null,
) {}
}
$latte->render('mail.latte', new MailTemplateParameters(
lang: $this->lang,
subject: $title,
price: $this->getPrice(),
items: [],
address: $userAddress,
));
変数の自動エスケープの無効化
変数に HTML 文字列が含まれている場合、Latte
が自動的に(したがって二重に)エスケープしないようにマークできます。これにより、テンプレートで
|noescape
を指定する必要がなくなります。
最も簡単な方法は、文字列を Latte\Runtime\Html
オブジェクトでラップすることです:
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
Latte はさらに、Latte\HtmlStringable
インターフェースを実装するすべてのオブジェクトをエスケープしません。したがって、__toString()
メソッドが自動的にエスケープされない HTML コードを返す独自のクラスを作成できます:
class Emphasis extends Latte\HtmlStringable
{
public function __construct(
private string $str,
) {
}
public function __toString(): string
{
return '<em>' . htmlspecialchars($this->str) . '</em>';
}
}
$params = [
'foo' => new Emphasis('hello'),
];
__toString
メソッドは正しい HTML
を返し、パラメータのエスケープを保証する必要があります。そうしないと、XSS
脆弱性が発生する可能性があります!
フィルタ、タグなどで Latte を拡張する方法
カスタムフィルタ、関数、タグなどを Latte に追加するにはどうすればよいですか?これについては、Latte の拡張の章で説明します。 変更をさまざまなプロジェクトで再利用したり、他の人と共有したりしたい場合は、拡張機能を作成する必要があります。
テンプレート内の任意のコード {php ...}
{do}
タグ内では PHP
式のみを記述できます。したがって、if ... else
などの構文やセミコロンで終わるステートメントを挿入することはできません。
ただし、{php ...}
タグを追加する RawPhpExtension
拡張機能を登録できます。これにより、任意の PHP
コードを挿入できます。サンドボックスモードのルールは適用されないため、使用はテンプレート作成者の責任となります。
$latte->addExtension(new Latte\Essential\RawPhpExtension);
生成されたコードのチェック
Latte はテンプレートを PHP
コードにコンパイルします。もちろん、生成されたコードが構文的に有効であることを保証します。ただし、サードパーティの拡張機能または
RawPhpExtension
を使用する場合、Latte は生成されたファイルの正確性を保証できません。
また、PHP では構文的に正しいが禁止されているコード(例えば、変数 $this
への値の代入)を記述することができ、PHP コンパイルエラーが発生します。
このような操作をテンプレートに記述すると、生成された PHP コードにも含まれます。PHP には約
200 の異なる禁止された操作があるため、Latte
はそれらを検出することを目指していません。通常、レンダリング時に PHP
自体がそれらを警告しますが、これは通常問題ありません。
ただし、テンプレートのコンパイル時に PHP
コンパイルエラーが含まれていないことを知りたい場合があります。特に、テンプレートをユーザーが編集できる場合、またはサンドボックスを使用している場合です。このような場合は、コンパイル時にテンプレートをチェックさせてください。
この機能は Engine::enablePhpLint()
メソッドで有効にします。チェックには PHP
バイナリを呼び出す必要があるため、そのパスをパラメータとして渡します:
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// Latte のエラーと PHP のコンパイルエラーをキャッチします
echo 'Error: ' . $e->getMessage();
}
ロケール
Latte
を使用すると、数値、日付、および並べ替えの書式設定に影響を与えるロケールを設定できます。これは
setLocale()
メソッドを使用して設定されます。ロケール識別子は、PHP 拡張機能
intl
が使用する IETF
言語タグ標準に従います。これは、言語コードと、場合によっては国コードで構成されます。例:米国の英語の場合は
en_US
、ドイツのドイツ語の場合は de_DE
など。
$latte = new Latte\Engine;
$latte->setLocale('cs');
ロケール設定は、フィルタ localDate、sort、number、および bytes に影響します。
PHP 拡張機能 intl
が必要です。Latte の設定は PHP
のグローバルロケール設定には影響しません。
厳格モード
厳格な解析モードでは、Latte は閉じ HTML タグが欠落していないかチェックし、変数
$this
の使用も禁止します。次のように有効にします:
$latte = new Latte\Engine;
$latte->setStrictParsing();
declare(strict_types=1)
ヘッダーを持つテンプレートの生成は、次のように有効にします:
$latte = new Latte\Engine;
$latte->setStrictTypes();
テンプレートでの翻訳
TranslatorExtension
拡張機能を使用すると、テンプレートにタグ {_...}
、{translate}
、およびフィルタ translate
を追加できます。これらは、値またはテンプレートの一部を他の言語に翻訳するために使用されます。パラメータとして、翻訳を実行するメソッド(PHP
callable)を指定します:
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// $original から $this->lang に従って $translated を作成します
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // PHP 8.0 では [$translator, 'translate']
);
$latte->addExtension($extension);
トランスレータは、テンプレートのレンダリング時に実行時に呼び出されます。ただし、Latte はテンプレートのコンパイル中にすべての静的テキストを翻訳できます。これにより、各文字列が 1 回だけ翻訳され、結果の翻訳がコンパイルされた形式に書き込まれるため、パフォーマンスが節約されます。したがって、キャッシュディレクトリには、言語ごとに 1 つずつ、複数のコンパイル済みバージョンのテンプレートが作成されます。これを行うには、言語を 2 番目のパラメータとして指定するだけです:
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
静的テキストとは、例えば {_'hello'}
や {translate}hello{/translate}
のようなものを意味します。{_$foo}
のような非静的テキストは、引き続き実行時に翻訳されます。
トランスレータには、{_$original, foo: bar}
または {translate foo: bar}
を使用してテンプレートから追加のパラメータを渡すこともできます。これらは配列
$params
として取得されます:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
デバッグと Tracy
Latte は開発をできるだけ快適にしようとします。デバッグ目的のために、3 つのタグ {dump}
、{debugbreak}
、{trace}
があります。
さらに優れたデバッグツール Tracyをインストールし、Latte アドオンを有効にすると、最高の快適さが得られます:
// Tracy を有効にします
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// Tracy の拡張機能を有効にします
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
これで、すべてのエラーが、行と列が強調表示されたテンプレートのエラーを含め、明確な赤い画面に表示されます(ビデオ)。 同時に、右下のいわゆる Tracy Bar に Latte のタブが表示され、レンダリングされたすべてのテンプレートとその相互関係(テンプレートまたはコンパイル済みコードにクリックして移動する可能性を含む)および変数が明確に表示されます:

Latte はテンプレートを読みやすい PHP コードにコンパイルするため、IDE で快適にステップ実行できます。
Linter:テンプレート構文の検証
Linter ツールは、すべてのテンプレートを調べて、構文エラーが含まれていないかチェックするのに役立ちます。コンソールから起動します:
vendor/bin/latte-lint <path>
--strict
パラメータは厳格モードを有効にします。
カスタムタグを使用している場合は、独自のバージョンの Linter
を作成します。例:custom-latte-lint
:
#!/usr/bin/env php
<?php
// autoload.php ファイルへの実際のパスを指定します
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// ここに個々の拡張機能を追加します
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
あるいは、カスタム Latte\Engine
オブジェクトを Linter に渡すこともできます:
$latte = new Latte\Engine;
// ここで $latte オブジェクトを設定します
$linter = new Latte\Tools\Linter(engine: $latte);
文字列からのテンプレートの読み込み
テスト目的などで、ファイルではなく文字列からテンプレートを読み込む必要がありますか?StringLoader が役立ちます:
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
例外ハンドラ
予期される例外に対して独自のハンドラを定義できます。{try}
内およびサンドボックス内で発生した例外が渡されます。
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
自動レイアウト検索
{layout}
タグを使用して、テンプレートはその親テンプレートを指定します。レイアウトを自動的に検索させることも可能です。これにより、テンプレートに
{layout}
タグを含める必要がなくなるため、テンプレートの記述が簡素化されます。
これは次の方法で実現されます:
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// レイアウトファイルへのパスを返します
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
テンプレートにレイアウトがない場合は、{layout none}
タグで示します。