Estensione di Latte
Latte è progettato pensando all'estensibilità. Sebbene il suo set standard di tag, filtri e funzioni copra molti casi d'uso, spesso è necessario aggiungere logica personalizzata specifica o strumenti di supporto. Questa pagina fornisce una panoramica dei modi per estendere Latte in modo che corrisponda perfettamente ai requisiti del vostro progetto – da semplici helper a nuove sintassi complesse.
Modi per estendere Latte
Ecco una rapida panoramica dei principali modi in cui potete personalizzare ed estendere Latte:
- Filtri personalizzati: Per formattare o trasformare i dati
direttamente nell'output del template (es.
{$var|myFilter}
). Ideale per compiti come la formattazione delle date, la modifica del testo o l'applicazione di un escaping specifico. Potete anche usarli per modificare blocchi più grandi di contenuto HTML avvolgendo il contenuto in un{block}
anonimo e applicandovi un filtro personalizzato. - Funzioni personalizzate: Per aggiungere logica riutilizzabile
che può essere chiamata all'interno delle espressioni nel template (es.
{myFunction($arg1, $arg2)}
). Utile per calcoli, accesso a funzioni di supporto dell'applicazione o generazione di piccole parti di contenuto. - Tag personalizzati: Per creare costrutti linguistici completamente
nuovi (
{mytag}...{/mytag}
on:mytag
). I tag offrono la massima flessibilità, consentendo di definire strutture personalizzate, controllare il parsing del template e implementare logiche di rendering complesse. - Passaggi di compilazione: Funzioni che modificano l'albero sintattico astratto (AST) del template dopo il parsing, ma prima della generazione del codice PHP. Vengono utilizzati per ottimizzazioni avanzate, controlli di sicurezza (come Sandbox) o modifiche automatiche del codice.
- Loader personalizzati: Per modificare il modo in cui Latte cerca e carica i file dei template (es. caricamento da database, storage crittografato, ecc.).
La scelta del metodo di estensione corretto è fondamentale. Prima di creare un tag complesso, considerate se un filtro o una funzione più semplice potrebbero essere sufficienti. Vediamo un esempio: implementazione di un generatore Lorem ipsum che accetta come argomento il numero di parole da generare.
- Come tag?
{lipsum 40}
– Possibile, ma i tag sono più adatti per strutture di controllo o per generare markup complessi. I tag non possono essere utilizzati direttamente nelle espressioni. - Come filtro?
{=40|lipsum}
– Tecnicamente funziona, ma i filtri sono progettati per trasformare il valore di input. Qui,40
è un argomento, non un valore che viene trasformato. Questo sembra semanticamente errato. - Come funzione?
{lipsum(40)}
– Questa è la soluzione più naturale! Le funzioni accettano argomenti e restituiscono valori, il che è ideale per l'uso in qualsiasi espressione:{var $text = lipsum(40)}
.
Raccomandazione generale: Utilizzate le funzioni per calcoli/generazione, i filtri per la trasformazione e i tag per nuovi costrutti linguistici o markup complessi. Utilizzate i passaggi per la manipolazione dell'AST e i loader per ottenere i template.
Registrazione diretta
Per strumenti di supporto specifici del progetto o estensioni rapide, Latte consente la registrazione diretta di filtri e
funzioni nell'oggetto Latte\Engine
.
Per registrare un filtro, utilizzate il metodo addFilter()
. Il primo argomento della vostra funzione filtro sarà
il valore prima del carattere |
e gli argomenti successivi sono quelli passati dopo i due punti :
.
$latte = new Latte\Engine;
// Definizione del filtro (oggetto richiamabile: funzione, metodo statico, ecc.)
$myTruncate = fn(string $s, int $length = 50) => mb_substr($s, 0, $length);
// Registrazione
$latte->addFilter('truncate', $myTruncate);
// Utilizzo nel template: {$text|truncate} o {$text|truncate:100}
Potete anche registrare un Filter Loader, una funzione che fornisce dinamicamente oggetti richiamabili di filtri in base al nome richiesto:
$latte->addFilterLoader(fn(string $name) => /* restituisce un oggetto richiamabile o null */);
Per registrare una funzione utilizzabile nelle espressioni del template, utilizzate addFunction()
.
$latte = new Latte\Engine;
// Definizione della funzione
$isWeekend = fn(DateTimeInterface $date) => $date->format('N') >= 6;
// Registrazione
$latte->addFunction('isWeekend', $isWeekend);
// Utilizzo nel template: {if isWeekend($myDate)}Weekend!{/if}
Per maggiori informazioni, consultate le sezioni Creazione di filtri personalizzati e Funzioni.
Metodo robusto: Estensione Latte
Sebbene la registrazione diretta sia semplice, il modo standard e raccomandato per impacchettare e distribuire le estensioni Latte è tramite le classi Extension. Un'estensione funge da punto di configurazione centrale per la registrazione di più tag, filtri, funzioni, passaggi di compilazione e altri elementi.
Perché usare le estensioni?
- Organizzazione: Mantiene insieme le estensioni correlate (tag, filtri, ecc. per una funzionalità specifica) in un'unica classe.
- Riutilizzabilità e condivisione: Impacchettate facilmente le vostre estensioni per l'uso in altri progetti o per la condivisione con la comunità (ad es. tramite Composer).
- Piena potenza: Tag personalizzati e passaggi di compilazione possono essere registrati solo tramite le estensioni.
Registrazione di un'estensione
Un'estensione viene registrata in Latte utilizzando il metodo addExtension()
(o tramite il file di configurazione):
$latte = new Latte\Engine;
$latte->addExtension(new MyProjectExtension);
Se registrate più estensioni e queste definiscono tag, filtri o funzioni con lo stesso nome, l'estensione aggiunta per ultima ha la precedenza. Ciò significa anche che le vostre estensioni possono sovrascrivere tag/filtri/funzioni nativi.
Ogni volta che apportate una modifica alla classe e l'aggiornamento automatico non è disabilitato, Latte ricompilerà automaticamente i vostri template.
Creazione di un'estensione
Per creare la vostra estensione, dovete creare una classe che erediti da Latte\Extension. Per avere un'idea di come appare un'estensione del genere, date un'occhiata alla CoreExtension integrata.
Diamo un'occhiata ai metodi che potete implementare:
beforeCompile (Latte\Engine $engine): void
Chiamato prima della compilazione del template. Il metodo può essere utilizzato, ad esempio, per inizializzazioni relative alla compilazione.
getTags(): array
Chiamato durante la compilazione del template. Restituisce un array associativo nome tag ⇒ oggetto richiamabile, che sono funzioni per il parsing dei tag. Maggiori informazioni.
public function getTags(): array
{
return [
'foo' => FooNode::create(...),
'bar' => BarNode::create(...),
'n:baz' => NBazNode::create(...),
// ...
];
}
Il tag n:baz
rappresenta un puro n:attributo, cioè
un tag che può essere scritto solo come attributo.
Per i tag foo
e bar
, Latte riconosce automaticamente se sono tag accoppiati e, in tal caso, possono
essere scritti automaticamente utilizzando n:attributi, incluse le varianti con i prefissi n:inner-foo
e
n:tag-foo
.
L'ordine di esecuzione di tali n:attributi è determinato dal loro ordine nell'array restituito dal metodo
getTags()
. Quindi n:foo
viene sempre eseguito prima di n:bar
, anche se gli attributi nel
tag HTML sono elencati nell'ordine opposto come <div n:bar="..." n:foo="...">
.
Se è necessario specificare l'ordine degli n:attributi tra più estensioni, utilizzate il metodo helper order()
,
dove il parametro before
xor after
specifica quali tag sono ordinati prima o dopo il tag.
public function getTags(): array
{
return [
'foo' => self::order(FooNode::create(...), before: 'bar')]
'bar' => self::order(BarNode::create(...), after: ['block', 'snippet'])]
];
}
getPasses(): array
Chiamato durante la compilazione del template. Restituisce un array associativo nome passaggio ⇒ oggetto richiamabile, che sono funzioni che rappresentano i cosiddetti passaggi di compilazione, che attraversano e modificano l'AST.
Anche qui è possibile utilizzare il metodo helper order()
. Il valore dei parametri before
o
after
può essere *
con il significato di prima/dopo tutto.
public function getPasses(): array
{
return [
'optimize' => Passes::optimizePass(...),
'sandbox' => self::order($this->sandboxPass(...), before: '*'),
// ...
];
}
beforeRender (Latte\Engine $engine): void
Chiamato prima di ogni rendering del template. Il metodo può essere utilizzato, ad esempio, per inizializzare le variabili utilizzate durante il rendering.
getFilters(): array
Chiamato prima del rendering del template. Restituisce i filtri come un array associativo nome filtro ⇒ oggetto richiamabile. Maggiori informazioni.
public function getFilters(): array
{
return [
'batch' => $this->batchFilter(...),
'trim' => $this->trimFilter(...),
// ...
];
}
getFunctions(): array
Chiamato prima del rendering del template. Restituisce le funzioni come un array associativo nome funzione ⇒ oggetto richiamabile. Maggiori informazioni.
public function getFunctions(): array
{
return [
'clamp' => $this->clampFunction(...),
'divisibleBy' => $this->divisibleByFunction(...),
// ...
];
}
getProviders(): array
Chiamato prima del rendering del template. Restituisce un array di provider, che sono solitamente oggetti utilizzati dai tag in
fase di esecuzione. Vi si accede tramite $this->global->...
. Maggiori informazioni.
public function getProviders(): array
{
return [
'myFoo' => $this->foo,
'myBar' => $this->bar,
// ...
];
}
getCacheKey (Latte\Engine $engine): mixed
Chiamato prima del rendering del template. Il valore restituito diventa parte della chiave, il cui hash è contenuto nel nome del file del template compilato. Pertanto, per valori restituiti diversi, Latte genererà file di cache diversi.