Създаване на персонализирани функции

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

Какво са функциите?

Функциите в Latte ви позволяват да разширите набора от функции, които могат да бъдат извиквани в рамките на изрази в шаблоните ({...}). Можете да си ги представите като персонализирани PHP функции, достъпни само вътре във вашите Latte шаблони. Това носи няколко предимства:

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

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

{if hasPermission('article', 'edit')}
    <a href="...">Редактиране</a>
{/if}

Без замърсяване на глобалното пространство: За разлика от дефинирането на истинска глобална функция в PHP, функциите на Latte съществуват само в контекста на рендиране на шаблона. Не е необходимо да натоварвате глобалното именно пространство на PHP с помощници, които са специфични само за шаблоните.

Интеграция с логиката на приложението: PHP callable обектът, стоящ зад функцията на Latte, може да бъде всичко – анонимна функция, статичен метод или метод на инстанция. Това означава, че вашите функции в шаблоните могат лесно да достъпват услуги на приложението, бази данни, конфигурация или всякаква друга необходима логика чрез улавяне на променливи (в случай на анонимни функции) или с помощта на dependency injection (в случай на обекти). Горният пример hasPermission ясно демонстрира това, като вероятно извиква на заден план услуга за авторизация.

Презаписване на нативни функции (незадължително): Можете дори да дефинирате функция на Latte със същото име като нативна PHP функция. В шаблона ще бъде извикана вашата собствена версия вместо оригиналната функция. Това може да бъде полезно за предоставяне на поведение, специфично за шаблона, или за осигуряване на последователна обработка (напр. гарантиране, че strlen винаги ще бъде многобайтово безопасна). Използвайте тази функция внимателно, за да избегнете недоразумения.

По подразбиране Latte позволява извикването на всички нативни PHP функции (ако не са ограничени от Sandbox). Персонализираните функции разширяват тази вградена библиотека със специфичните нужди на вашия проект.

Ако само трансформирате единична стойност, може да е по-подходящо да използвате персонализиран филтър.

Създаване и регистриране на функции

Подобно на филтрите, има няколко начина за дефиниране и регистриране на персонализирани функции.

Директна регистрация с 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\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, могат да бъдат подкрепени от методи на обекти, които могат да имат свои собствени зависимости, управлявани от контейнера за dependency injection на вашето приложение или фабрика. Това поддържа логиката на вашите шаблони свързана с ядрото на приложението, като същевременно запазва ясна организация.

Функции, използващи клас с атрибути

Подобно на филтрите, функциите могат да бъдат дефинирани като методи във вашия клас на параметри на шаблона с помощта на атрибута #[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