カスタム関数の作成

Latteテンプレートにカスタムヘルパー関数を簡単に追加できます。計算、サービスへのアクセス、または動的コンテンツの生成のために、式内で直接PHPロジックを呼び出し、テンプレートをクリーンで強力に保ちます。

関数とは?

Latteの関数を使用すると、テンプレート内の式({...})内で呼び出すことができる関数のセットを拡張できます。これらは、Latteテンプレート内でのみ利用可能なカスタムPHP関数と考えることができます。これにはいくつかの利点があります:

利便性: ヘルパーロジック(計算、フォーマット、アプリケーションデータへのアクセスなど)を定義し、PHPで strlen()date() を呼び出すのと同じように、テンプレート内で直接、シンプルで使い慣れた関数構文を使用して呼び出すことができます。

{var $userInitials = initials($userName)} {* 例:'J. D.' *}

{if hasPermission('article', 'edit')}
    <a href="...">Edit</a>
{/if}

グローバルスコープの汚染なし: PHPで実際のグローバル関数を定義するのとは異なり、Latte関数はテンプレートレンダリングコンテキスト内でのみ存在します。テンプレート固有のヘルパーでPHPグローバル名前空間を汚染する必要はありません。

アプリケーションロジックとの統合: Latte関数の背後にあるPHP callableは、クロージャ、静的メソッド、またはインスタンスメソッドなど、何でもかまいません。これは、テンプレート内の関数が、変数をキャプチャする(クロージャの場合)か、依存性注入を使用する(オブジェクトの場合)ことによって、アプリケーションサービス、データベース、設定、またはその他の必要なロジックに簡単にアクセスできることを意味します。上記の hasPermission の例は、おそらくバックグラウンドで認証サービスを呼び出すことによって、これを明確に示しています。

ネイティブ関数の上書き(オプション): ネイティブPHP関数と同じ名前のLatte関数を定義することもできます。テンプレートでは、元の関数の代わりにカスタムバージョンが呼び出されます。これは、テンプレート固有の動作を提供したり、一貫した処理を保証したりするのに役立ちます(たとえば、strlen が常にマルチバイトセーフであることを保証するなど)。誤解を避けるために、この機能は慎重に使用してください。

デフォルトでは、LatteはすべてのネイティブPHP関数の呼び出しを許可します(Sandboxによって制限されていない限り)。カスタム関数は、プロジェクト固有のニーズに合わせてこの組み込みライブラリを拡張します。

単一の値を変換するだけの場合は、カスタムフィルタを使用する方が適切な場合があります。

関数の作成と登録

フィルタと同様に、カスタム関数を定義および登録するにはいくつかの方法があります。

addFunction() を使用した直接登録

最も簡単な方法は、Latte\Engine オブジェクトで addFunction() を使用することです。関数名(テンプレートに表示される名前)と対応するPHP callableを指定します。

$latte = new Latte\Engine;

// シンプルなヘルパー関数
$latte->addFunction('initials', function (string $name): string {
	preg_match_all('#\b\w#u', $name, $m);
	return implode('. ', $m[0]) . '.';
});

テンプレートでの使用:

{var $userInitials = initials($userName)}

テンプレート内の関数引数は、PHP callableに同じ順序で直接渡されます。型ヒント、デフォルト値、可変長引数(...)などのPHP機能は期待どおりに機能します。

拡張機能による登録

より良い整理と再利用性のために、Latte拡張機能内で関数を登録します。このアプローチは、より複雑なアプリケーションや共有ライブラリに推奨されます。

namespace App\Latte;

use Latte\Extension;
use Nette\Security\Authorizator;

class MyLatteExtension extends Extension
{
	public function __construct(
		// Authorizatorサービスが存在すると仮定します
		private Authorizator $authorizator,
	) {
	}

	public function getFunctions(): array
	{
		// メソッドをLatte関数として登録します
		return [
			'hasPermission' => $this->hasPermission(...),
		];
	}

	public function hasPermission(string $resource, string $action): bool
	{
		return $this->authorizator->isAllowed($resource, $action);
	}
}

// 登録($containerがDICを含むと仮定します)
$extension = $container->getByType(App\Latte\MyLatteExtension::class);
$latte = new Latte\Engine;
$latte->addExtension($extension);

このアプローチは、Latteで定義された関数が、アプリケーションの依存性注入コンテナまたはファクトリによって管理される独自の依存関係を持つことができるオブジェクトメソッドによってどのようにバックアップされるかを明確に示しています。これにより、テンプレートロジックがアプリケーションコアに接続され、クリーンな整理が維持されます。

属性付きクラスを使用した関数

フィルタと同様に、関数は #[Latte\Attributes\TemplateFunction] 属性を使用してテンプレートパラメータクラスのメソッドとして定義できます。

use Latte\Attributes\TemplateFunction;

class TemplateParameters
{
	public function __construct(
		public string $userName,
		// その他のパラメータ...
	) {}

	// このメソッドはテンプレート内で {initials(...)} として利用可能になります
	#[TemplateFunction]
	public function initials(string $name): string
	{
		preg_match_all('#\b\w#u', $name, $m);
		return implode('. ', $m[0]) . '.';
	}
}

// オブジェクトをテンプレートに渡す
$params = new TemplateParameters(userName: 'John Doe', /* ... */);
$latte->render('template.latte', $params);

パラメータオブジェクトがテンプレートに渡されると、Latteはこの属性でマークされたメソッドを自動的に検出して登録します。テンプレート内の関数名はメソッド名に対応します。

{* パラメータクラスで定義された関数を使用する *}
{var $inits = initials($userName)}

コンテキスト関数?

フィルタとは異なり、FilterInfo に似たオブジェクトを受け取る「コンテキスト関数」の直接的な概念はありません。関数は式内で動作し、通常、ブロックに適用されるフィルタと同じ方法でレンダリングコンテキストまたはコンテンツタイプ情報への直接アクセスを必要としません。

バージョン: 3.0