テンプレートローダー
ローダーとは、Latteがテンプレートのソースコードを取得するための仕組みです。一般的にテンプレートはディスクに保存されたファイルですが、Latteの柔軟なローダーシステムにより、事実上どこからでもテンプレートを読み込むことができ、また動的に生成することもできます。
ローダーとは?
通常、テンプレートを扱うとき、プロジェクトのディレクトリ構造に存在する.latte
ファイルを思い浮かべます。これはLatteのデフォルトのFileLoaderによって処理されます。しかし、('main.latte'
や'components/card.latte'
のような)テンプレート名と実際のソースコードの内容は、直接ファイルパスにマッピングされる必要はありません。
そこで、ローダーの出番です。ローダーはテンプレート名(識別子文字列)を受け取り、そのソースコードをLatteに提供する役割を担うオブジェクトです。Latteはこの作業を設定されたローダーに全面的に依存しています。これは、$latte->render('main.latte')
を介して要求された最初のテンプレートだけでなく、{include ...}
、{layout ...}
、{embed ...}
、{import ...}
のようなタグを使用して内部で参照されるすべてのテンプレートにも適用されます。
なぜカスタム・ローダーを使うのか?
- 代替ソースからのロード:**データベース、キャッシュ(RedisやMemcachedのような)、バージョン管理システム(Gitのような、特定のコミットに基づいて)、または動的に生成されたテンプレートに格納されているテンプレートを取得します。
- カスタムの命名規則を実装する:** テンプレートに短いエイリアスを使用したり、特定の検索パスロジック(例えば、最初にテーマディレクトリを探し、その後デフォルトディレクトリにフォールバックする)を実装したい場合があります。
- ** セキュリティやアクセス制御の追加:** カスタムローダーは、特定のテンプレートをロードする前にユーザーの権限を確認することができます。
- 前処理:** 一般的には推奨されませんが(コンパイラパスの方が良い)、Latteにテンプレートを渡す前にローダーが前処理を行うことは理論的には可能です。
setLoader()
メソッドを使用して、Latte\Engine
インスタンスのローダーを設定します:
$latte = new Latte\Engine;
// path/to/templates'内のファイルにはデフォルトのFileLoaderを使用する。
$loader = new Latte\Loaders\FileLoader('/path/to/templates');
$latte->setLoader($loader);```
ローダーは`Latte\Loader` インターフェースを実装しなければならない。
組み込みローダー .[#toc-built-in-loaders]
=================================
Latteにはいくつかの標準ローダーが用意されています:
ファイルローダー .[#toc-fileloader]
---------------------------
他のローダーが指定されていない場合、`Latte\Engine` が使用する **デフォルトのローダー** です。ファイルシステムから直接テンプレートをロードします。
アクセスを制限するために、オプションでルート・ディレクトリを設定できます:
```php
use Latte\Loaders\FileLoader;
// 以下のようにすると、/var/www/html/templates内のテンプレートしか読み込めなくなります。
latte->render('../../../etc/passwd'); // これは例外をスローします。
var/www/html/templates/pages/contact.latteにあるテンプレートをレンダリングします。
$loader = new FileLoader('/var/www/html/templates');
$latte->setLoader($loader);
//
//$latte->render('pages/contact.latte');```
`{include}` や`{layout}` のようなタグを使用する場合、絶対パスが与えられない限り、現在のテンプレートからの相対パスでテンプレート名を解決します。
文字列ローダー .[#toc-stringloader]
----------------------------
このローダは、連想配列からテンプレートの内容を取得します。 キーがテンプレート名 (識別子)、値がテンプレートのソースコード文字列となります。これは、テンプレートが PHP のコード自体に格納されているようなテスト用や小規模なアプリケーションで特に有用です。
```php
use Latte\Loaders\StringLoader;
$loader = new StringLoader([
'main.latte' => 'Hello {$name}, include is below:{include helper.latte}',
'helper.latte' => '{var $x = 10}Included content: {$x}',
// 必要に応じてテンプレートを追加
出力ハローワールド、インクルードは以下のとおりです:10
]);
$latte->setLoader($loader);
$latte->render('main.latte', ['name' => 'World']);
文字列から直接単一のテンプレートをレンダリングするだけでよく、
インクルードや他の名前付き文字列テンプレートを参照する継承は不要な場合は、render()
あるいはStringLoader
を配列なしで使用する場合はrenderToString()
に直接文字列を渡します:
$loader = new StringLoader;
$latte->setLoader($loader);
$templateString = 'Hello {$name}!';
$output = $latte->renderToString($templateString, ['name' => 'Alice']);
// outputに'Hello Alice!'が含まれる。
カスタムローダーの作成
独自のローダーを作成するには(データベース、キャッシュ、バージョン管理、その他のソースからテンプレートをロードするなど)、Latte\Loader インターフェイスを実装するクラスを作成する必要があります。
各メソッドが何をする必要があるか見てみましょう。
getContent (string $name): string
これはローダーの核となるメソッドです。このメソッドの責務は、$name
($latte->render()
に渡されたもの、またはgetReferredName()によって返されたもの)によって識別されるテンプレートの完全なソースコードの内容を取得して返すことです。
テンプレートが見つからないか、アクセスできない場合、このメソッドはLatte\RuntimeException
**
を投げなければなりません。
public function getContent(string $name): string
{
// 例仮想的な内部ストレージからのフェッチ
$content = $this->storage->read($name);
if ($content === null) {
throw new Latte\RuntimeException("Template '$name' cannot be loaded.");
}
return $content;
}```
getReferredName <span class=wiki-arguments>(*string* $name, *string* $referringName)</span><span class=wiki-arguments>: *string*</span> .{toc: getReferredName()}[wiki-method]
----------------------------------------------------------------------
このメソッドは、`{include}` 、`{layout}` などのタグ内で使用されるテンプレート名の解決を処理します。Latteは、例えば`main.latte` の中に`{include 'partial.latte'}` がある場合、`$name = 'partial.latte'` と`$referringName = 'main.latte'` を使ってこのメソッドを呼び出します。
このメソッドの仕事は、`$name` を、`$referringName` によって提供されるコンテキストに基づいて、他のローダーメソッドを呼び出すときに使用される正規の識別子(たとえば、絶対パスや一意のデータベースキー)に解決することです。
```php
public function getReferredName(string $name, string $referringName): string
{
return ...;
}
getUniqueId (string $name): string
Latteはパフォーマンスのためにコンパイルされたテンプレートキャッシュを使用します。各コンパイル済みテンプレートファイルは、ソーステンプレートの識別子から派生した一意な名前を必要とします。このメソッドは、テンプレート$name
を 一意に 識別する文字列を提供します。
ファイル・ベースのテンプレートでは、絶対パスが使えます。データベース・テンプレートの場合は、接頭辞とデータベース ID の組み合わせが一般的です。
public function getUniqueId(string $name): string
{
return ...;
}
例シンプルなデータベースローダー
この例では、name
(一意識別子)、content
、updated_at
のカラムを持つtemplates
というデータベーステーブルに格納されたテンプレートを取得するローダーの基本構造を示します。
use Latte;
class DatabaseLoader implements Latte\Loader
{
public function __construct(
private \PDO $db,
) {
}
public function getContent(string $name): string
{
$stmt = $this->db->prepare('SELECT content FROM templates WHERE name = ?');
$stmt->execute([$name]);
$content = $stmt->fetchColumn();
if ($content === false) {
throw new Latte\RuntimeException("Template '$name' not found in database.");
}
return $content;
}
// この単純な例では、テンプレート名('homepage'、'article'など)が一意なIDであり、テンプレートがお互いを相対的に参照しないと仮定しています。
はユニークなIDであり、テンプレートは相対的にお互いを参照しません。
接頭辞と名前そのものを使えば、一意で十分です。
使い方
DBから'homepage'という名前のテンプレートをロードする
// public function getReferredName(string $name, string $referringName): string
{
return $name;
}
public function getUniqueId(string $name): string
{
// return 'db_' . $name;
}
}
//$pdo = new \PDO(/* connection details */);
$loader = new DatabaseLoader($pdo);
$latte->setLoader($loader);
$latte->render('homepage');
カスタムローダーは、Latteテンプレートがどこから来るかを完全にコントロールし、様々なストレージシステムやワークフローとの統合を可能にします。