Создание пользовательских функций

Легко добавляйте в шаблоны Latte пользовательские вспомогательные функции. Вызывайте PHP-логику непосредственно в выражениях для вычислений, доступа к сервисам или генерации динамического контента, что сохранит ваши шаблоны чистыми и мощными.

Что такое функции?

Функции в Latte позволяют расширить набор функций, которые можно вызывать в выражениях в шаблонах ({...}). Вы можете представить их как пользовательские PHP-функции, доступные только внутри ваших Latte-шаблонов. Это дает несколько преимуществ:

Удобство: Вы можете определить вспомогательную логику (например, вычисления, форматирование или доступ к данным приложения) и вызывать ее с помощью простого, знакомого синтаксиса функций прямо в шаблоне, так же, как вы бы вызвали strlen() или date() в PHP.

{var $userInitials = initials($userName)} {* например, 'J. D.' *}

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

Без загрязнения глобального пространства: В отличие от определения настоящей глобальной функции в PHP, функции Latte существуют только в контексте рендеринга шаблона. Вам не нужно загружать глобальное пространство имен PHP помощниками, специфичными только для шаблонов.

Интеграция с логикой приложения: PHP-вызываемый объект, стоящий за функцией Latte, может быть чем угодно — анонимной функцией, статическим методом или методом экземпляра. Это означает, что ваши функции в шаблонах могут легко получать доступ к службам приложения, базам данных, конфигурации или любой другой необходимой логике, захватывая переменные (в случае анонимных функций) или используя внедрение зависимостей (в случае объектов). Вышеприведенный пример hasPermission ясно демонстрирует это, когда, вероятно, вызывает на заднем плане службу авторизации.

Переопределение нативных функций (необязательно): Вы можете даже определить функцию Latte с тем же именем, что и у нативной PHP-функции. В шаблоне вместо исходной функции будет вызвана ваша собственная версия. Это может быть полезно для предоставления поведения, специфичного для шаблона, или обеспечения согласованной обработки (например, гарантируя, что strlen всегда будет многобайтово безопасной). Используйте эту функцию с осторожностью, чтобы избежать недоразумений.

По умолчанию Latte позволяет вызывать все нативные PHP-функции (если они не ограничены Песочницей). Пользовательские функции расширяют эту встроенную библиотеку специфическими потребностями вашего проекта.

Если вы просто преобразуете одно значение, может быть более подходящим использовать пользовательский фильтр.

Создание и регистрация функций

Аналогично фильтрам, существует несколько способов определения и регистрации пользовательских функций.

Прямая регистрация с помощью addFunction()

Самый простой метод — использовать addFunction() на объекте Latte\Engine. Вы указываете имя функции (как оно будет отображаться в шаблоне) и соответствующий PHP-вызываемый объект.

$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-вызываемому объекту в том же порядке. Функциональность 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