Создание пользовательских функций
Легко добавляйте собственные вспомогательные функции в шаблоны 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-callable, стоящий за функцией Latte,
может быть чем угодно: замыканием, статическим методом или методом
экземпляра. Это значит, что ваши функции шаблонов легко получают
доступ к сервисам приложения, базам данных, конфигурации или любой
другой нужной логике через захват переменных (в замыканиях) или через
внедрение зависимостей (в объектах). Пример hasPermission выше
наглядно это показывает: он, скорее всего, вызывает в фоне сервис
авторизации.
Переопределение нативных функций (по желанию): вы можете даже
определить функцию Latte с тем же именем, что и у нативной функции PHP.
Внутри шаблона будет вызвана ваша версия. Это может пригодиться, чтобы
задать поведение, специфичное для шаблонов, или обеспечить
единообразную обработку (например, сделать strlen всегда
безопасным для многобайтовых строк). Пользуйтесь этой возможностью
осторожно, чтобы не создавать путаницу.
По умолчанию Latte разрешает вызывать все нативные функции PHP (если их не ограничивает песочница). Пользовательские функции дополняют эту встроенную библиотеку тем, что нужно именно вашему проекту.
Если вы преобразуете одно значение, более уместным может быть пользовательский фильтр.
Создание и регистрация функций
Как и у фильтров, есть несколько способов определить и зарегистрировать пользовательские функции.
Прямая регистрация через
addFunction()
Самый простой способ – использовать addFunction() на объекте
Latte\Engine. Вы указываете имя функции (каким оно будет в шаблоне) и
соответствующий 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\Templating;
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 содержит DI-контейнер)
$extension = $container->getByType(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. Но
функция может получить доступ к контексту шаблона: если её первый
параметр объявлен с типом Latte\Runtime\Template, Latte автоматически
передаст ей объект текущего шаблона. Именно так реализованы
встроенные функции hasBlock() и hasTemplate().