開発者向けプラクティス
インストール
Latteのインストールには、Composerを使うのが一番です。
composer require latte/latte
対応するPHPのバージョン(最新のパッチLatteのバージョンに適用されます)。
バージョン|PHPと互換性がある | |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
テンプレートのレンダリング方法
テンプレートをレンダリングする方法は?この簡単なコードを使うだけです。
$latte = new Latte\Engine;
// cache directory
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* template variables */ ];
// or $params = new TemplateParameters(/* ... */);
// render to output
$latte->render('template.latte', $params);
// or render to variable
$output = $latte->renderToString('template.latte', $params);
パラメータには配列やオブジェクトを指定することができ、エディターで型チェックやサジェストを行うことができます。
また、Latte examplesというリポジトリで使用例を見ることができます。
パフォーマンスとキャッシング
Latteのテンプレートは非常に高速です。Latteはテンプレートを直接PHPコードにコンパイルし、ディスク上にキャッシュしているからです。したがって、純粋なPHPで書かれたテンプレートと比較して、余分なオーバーヘッドがありません。
キャッシュは、ソースファイルを変更するたびに自動的に再生成されます。そのため、開発中にLatteのテンプレートを編集しても、すぐにブラウザで変更内容を確認できる便利な機能です。本番環境ではこの機能を無効にして、パフォーマンスを少し節約することができます。
$latte->setAutoRefresh(false);
本番サーバーに導入した場合、特に大規模なアプリケーションの場合、最初のキャッシュ生成には当然ながら時間がかかることがあります。Latteは「キャッシュスタンピード」に対する:https://en.wikipedia.org/…che_stampede予防策を内蔵しています。 これは、サーバーが多数の同時リクエストを受け、Latteのキャッシュがまだ存在しないため、それらがすべて同時にキャッシュを生成してしまう状況です。これがCPUを急上昇させるのです。 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の拡張の章を参照してください。 変更した内容を別のプロジェクトで再利用したい場合や、他の人と共有したい場合は、拡張機能を作成する必要があります。
テンプレート内の任意のコード{php ...}
の中に書くことができるのは、PHPの式だけです。 {do}
タグを使用するため、例えば、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) {
// PHPのラテ・エラーとコンパイル・エラーをキャッチする
echo 'Error: ' . $e->getMessage();
}
ロケール
Latteではロケールを設定することができます。ロケールは数値、日付、ソートのフォーマットに影響します。ロケールはsetLocale()
。ロケール識別子は IETF の言語タグ標準に従い、PHP のintl
拡張モジュールを使用します。これは、言語コードと場合によっては国コードで構成されます。
たとえば、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
{
// create $translated from $original according to $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] in PHP 8.0
);
$latte->addExtension($extension);
トランスレータは、テンプレートがレンダリングされるときに実行時に呼び出されます。しかし、Latteはテンプレートのコンパイル時にすべての静的テキストを翻訳することができます。これは、各文字列が一度だけ翻訳され、その結果の翻訳がコンパイルされたファイルに書き込まれるため、パフォーマンスを節約することができます。これにより、キャッシュディレクトリに、各言語ごとに複数のコンパイル済みバージョンのテンプレートが作成されます。これを行うには、第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'
}
デバッグとトレイシー
ラテは、できるだけ快適に開発できるように心がけています。デバッグのために、以下の3つのタグを用意しています。
{dump}
, {debugbreak}
と {trace}
.
優れたデバッグツールであるTracyをインストールし、Latteプラグインを有効化すれば、最も快適になります。
// enables Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// activates Tracy's extension
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
これで、行と列が強調表示されたテンプレート内のエラーも含め、すべてのエラーがきちんと赤い画面で確認できるようになります(動画)。 同時に、右下のいわゆるトレーシーバーにラテのタブが表示され、レンダリングされたすべてのテンプレートとその関係(テンプレートやコンパイルされたコードにクリックする可能性を含む)、および変数を明確に見ることができます。
Latteはテンプレートを読みやすいPHPコードにコンパイルするので、IDEでステップを踏んでいけるのが便利です。
リンターテンプレートの構文を検証する
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 に渡すこともできます:
```php
$latte = new Latte\Engine;
// ここでは、$latteオブジェクトを設定します。
$linter = new Latte\Tools\Linter(engine: $latte);```
文字列からテンプレートを読み込む .[#toc-loading-templates-from-a-string]
========================================================
テスト用に、ファイルではなく文字列からテンプレートをロードする必要がありますか?[StringLoaderは |extending-latte#stringloader]、そんなあなたのお役に立ちます。
```php
$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()) {
// it returns the path to the parent template file
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
テンプレートがレイアウトを持つべきではない場合は、{layout none}
タグでその旨を表示します。