テンプレートローダー

ローダーとは、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 (一意識別子)、contentupdated_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テンプレートがどこから来るかを完全にコントロールし、様々なストレージシステムやワークフローとの統合を可能にします。

バージョン: 3.0