Creare funzioni personalizzate

Aggiungete facilmente le vostre funzioni di supporto ai template Latte. Richiamate la logica PHP direttamente nelle espressioni per eseguire calcoli, accedere ai servizi o generare contenuti dinamici, mantenendo i template puliti ed espressivi.

Cosa sono le funzioni?

Le funzioni di Latte permettono di ampliare l'insieme delle funzioni richiamabili nelle espressioni del template ({...}). Consideratele come funzioni PHP personalizzate disponibili solo all'interno dei vostri template Latte. Questo porta diversi vantaggi:

Comodità: potete definire logica di supporto (calcoli, formattazione, accesso ai dati dell'applicazione) e richiamarla nel template con una sintassi di funzione semplice e familiare, esattamente come chiamereste strlen() o date() in PHP.

{var $userInitials = initials($userName)} {* per esempio 'J. D.' *}

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

Nessun inquinamento dello spazio globale: a differenza di una vera funzione globale in PHP, le funzioni di Latte esistono solo nel contesto del rendering del template. Non dovete ingombrare il namespace globale di PHP con funzioni di supporto specifiche dei template.

Integrazione con la logica applicativa: il callable PHP dietro a una funzione di Latte può essere qualsiasi cosa: una closure, un metodo statico o un metodo di istanza. Questo significa che le funzioni dei vostri template possono accedere facilmente ai servizi dell'applicazione, ai database, alla configurazione o a qualsiasi altra logica necessaria, catturando variabili (nelle closure) oppure tramite dependency injection (negli oggetti). L'esempio hasPermission qui sopra lo mostra chiaramente: con ogni probabilità chiama un servizio di autorizzazione in background.

Sovrascrivere funzioni native (facoltativo): potete perfino definire una funzione Latte con lo stesso nome di una funzione nativa di PHP. Nel template verrà chiamata la vostra versione personalizzata. Può essere utile per fornire un comportamento specifico dei template o per garantire una gestione coerente (per esempio rendere strlen sempre sicuro sui caratteri multibyte). Usate questa possibilità con cautela, per non creare confusione.

Per impostazione predefinita Latte consente di chiamare tutte le funzioni native di PHP (a meno che non le limiti la Sandbox). Le funzioni personalizzate integrano questa libreria predefinita con le esigenze specifiche del vostro progetto.

Se state trasformando un singolo valore, un filtro personalizzato è probabilmente più idiomatico.

Creare e registrare le funzioni

Come per i filtri, ci sono diversi modi di definire e registrare funzioni personalizzate.

Registrazione diretta con addFunction()

Il metodo più semplice è usare addFunction() sull'oggetto Latte\Engine. Indicate il nome della funzione (così come comparirà nel template) e il corrispondente callable PHP.

$latte = new Latte\Engine;

// semplice funzione di supporto
$latte->addFunction('initials', function (string $name): string {
	preg_match_all('#\b\w#u', $name, $m);
	return implode('. ', $m[0]) . '.';
});

Uso nel template:

{var $userInitials = initials($userName)}

Gli argomenti della funzione nel template vengono passati direttamente al callable PHP nello stesso ordine. Le funzionalità di PHP come le dichiarazioni di tipo, i valori predefiniti e i parametri variadici (...) funzionano come previsto.

Registrazione tramite estensione

Per una migliore organizzazione e riusabilità, registrate le funzioni all'interno di un'estensione di Latte. È l'approccio consigliato per le applicazioni non banali e per le librerie condivise.

namespace App\Templating;

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

class MyLatteExtension extends Extension
{
	public function __construct(
		// si presume che il servizio Authorizator esista
		private Authorizator $authorizator,
	) {
	}

	public function getFunctions(): array
	{
		// registra i metodi come funzioni di Latte
		return [
			'hasPermission' => $this->hasPermission(...),
		];
	}

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

// registrazione (si presume che $container contenga il container DI)
$extension = $container->getByType(MyLatteExtension::class);
$latte = new Latte\Engine;
$latte->addExtension($extension);

Questo approccio mostra chiaramente come le funzioni definite in Latte possano essere sostenute da metodi di oggetti che, a loro volta, possono avere dipendenze gestite dal container di dependency injection o dalla factory della vostra applicazione. In questo modo la logica dei template resta collegata al cuore dell'applicazione senza perdere in organizzazione.

Funzioni tramite una classe con attributi

Proprio come i filtri, le funzioni possono essere definite come metodi della vostra classe dei parametri del template usando l'attributo #[Latte\Attributes\TemplateFunction].

use Latte\Attributes\TemplateFunction;

class TemplateParameters
{
	public function __construct(
		public string $userName,
		// altri parametri...
	) {}

	// questo metodo diventa disponibile nel template come {initials(...)}
	#[TemplateFunction]
	public function initials(string $name): string
	{
		preg_match_all('#\b\w#u', $name, $m);
		return implode('. ', $m[0]) . '.';
	}
}

// passa l'oggetto al template
$params = new TemplateParameters(userName: 'John Doe', /* ... */);
$latte->render('template.latte', $params);

Latte individua e registra automaticamente i metodi contrassegnati con questo attributo quando l'oggetto dei parametri viene passato al template. Il nome della funzione nel template corrisponde al nome del metodo.

{* usa la funzione definita nella classe dei parametri *}
{var $inits = initials($userName)}

Funzioni contestuali?

A differenza dei filtri, le funzioni non ricevono un oggetto FilterInfo. Una funzione può però ottenere accesso al contesto del template: se il suo primo parametro è dichiarato di tipo Latte\Runtime\Template, Latte le passa automaticamente l'oggetto del template corrente. È esattamente così che sono implementate le funzioni integrate hasBlock() e hasTemplate().

versione: 3.x