Loader
I loader sono il meccanismo con cui Latte recupera il codice sorgente dei vostri template. Nella maggior parte dei casi i template sono file salvati su disco, ma il flessibile sistema di loader di Latte permette di caricarli praticamente da qualsiasi luogo, o perfino di generarli dinamicamente.
Cos'è un loader?
Di solito, lavorando con i template, si pensa a file .latte che si trovano nella struttura di directory del
progetto. Di questo si occupa il FileLoader predefinito di Latte. Il legame tra il nome di un
template (per esempio 'main.latte' o 'components/card.latte') e il contenuto del suo codice sorgente non
deve però per forza essere una corrispondenza diretta con un percorso di file.
Ed è qui che entrano in gioco i loader. Un loader è un oggetto che ha il compito di prendere un nome di template (una
stringa identificativa) e fornire a Latte il relativo codice sorgente. Per questo compito Latte si affida interamente al loader
configurato. Ciò vale non solo per il template iniziale richiesto con $latte->render('main.latte'), ma anche per
ogni template referenziato al suo interno con tag come {include ...}, {layout ...},
{embed ...} o {import ...}.
Perché usare un loader personalizzato?
- Caricamento da fonti alternative: recuperare template salvati in un database, in una cache (come Redis o Memcached), in un sistema di controllo di versione (come Git, a partire da un commit specifico) oppure generati dinamicamente.
- Convenzioni di denominazione proprie: potreste voler usare alias più brevi per i template o implementare una logica di ricerca specifica (per esempio cercare prima in una directory del tema e poi ripiegare su una directory predefinita).
- Sicurezza o controllo degli accessi: un loader personalizzato può verificare i permessi dell'utente prima di caricare determinati template.
- Preelaborazione: benché in generale sia sconsigliata (i compiler pass sono preferibili), un loader potrebbe teoricamente preelaborare il contenuto del template prima di consegnarlo a Latte.
Il loader di un'istanza di Latte\Engine si imposta con il metodo setLoader():
$latte = new Latte\Engine;
// usa il FileLoader predefinito per i file in '/path/to/templates'
$loader = new Latte\Loaders\FileLoader('/path/to/templates');
$latte->setLoader($loader);
Un loader deve implementare l'interfaccia Latte\Loader.
Loader integrati
Latte offre diversi loader standard:
FileLoader
È il loader predefinito usato dalla classe Latte\Engine se non ne viene indicato un altro. Carica
i template direttamente dal file system.
Potete facoltativamente impostare una directory radice per limitare l'accesso:
use Latte\Loaders\FileLoader;
// quanto segue permetterà di caricare i template solo dalla directory /var/www/html/templates
$loader = new FileLoader('/var/www/html/templates');
$latte->setLoader($loader);
// $latte->render('../../../etc/passwd'); // solleverebbe un'eccezione
// rendering di un template che si trova in /var/www/html/templates/pages/contact.latte
$latte->render('pages/contact.latte');
Con tag come {include} o {layout} risolve i nomi dei template relativamente al template corrente, a
meno che non venga indicato un percorso assoluto. Se però è impostata una directory radice, tutti i nomi vengono risolti
relativamente al template corrente.
StringLoader
Questo loader ricava il contenuto dei template da un array associativo, dove le chiavi sono i nomi (gli identificatori) dei template e i valori sono le stringhe con il loro codice sorgente. È particolarmente utile per i test o per piccole applicazioni in cui i template possono essere salvati direttamente nel codice PHP.
use Latte\Loaders\StringLoader;
$loader = new StringLoader([
'main.latte' => 'Ciao {$name}, segue include:{include helper.latte}',
'helper.latte' => '{var $x = 10}Contenuto incluso: {$x}',
// aggiungete altri template secondo necessità
]);
$latte->setLoader($loader);
$latte->render('main.latte', ['name' => 'World']);
// output: Ciao World, segue include:Contenuto incluso: 10
Se vi serve fare il rendering di un singolo template direttamente da una stringa, senza include né ereditarietà che facciano
riferimento ad altri template stringa denominati, potete passare la stringa direttamente al metodo render() o
renderToString() usando StringLoader senza array:
$loader = new StringLoader;
$latte->setLoader($loader);
$templateString = 'Ciao {$name}!';
$output = $latte->renderToString($templateString, ['name' => 'Alice']);
// $output contiene 'Ciao Alice!'
Creare un loader personalizzato
Per creare un vostro loader (per esempio per caricare i template da un database, da una cache, da un sistema di controllo di versione o da un'altra fonte) dovete creare una classe che implementi l'interfaccia Latte\Loader.
Vediamo cosa deve fare ciascun metodo.
getContent (string $name): string
È il metodo centrale del loader. Il suo compito è recuperare e restituire l'intero codice sorgente del template identificato
da $name (così come è stato passato al metodo $latte->render() o restituito dal metodo getReferredName()).
Se il template non può essere trovato o non è accessibile, questo metodo deve sollevare l'eccezione
Latte\TemplateNotFoundException.
public function getContent(string $name): string
{
// esempio: caricamento da un ipotetico storage interno
$content = $this->storage->read($name);
if ($content === null) {
throw new Latte\TemplateNotFoundException("Impossibile caricare il template '$name'.");
}
return $content;
}
getReferredName (string $name, string $referringName): string
Questo metodo si occupa di risolvere i nomi dei template usati all'interno di tag come {include},
{layout} e simili. Quando Latte incontra, per esempio, {include 'partial.latte'} dentro
main.latte, chiama questo metodo con $name = 'partial.latte' e
$referringName = 'main.latte'.
Il compito del metodo è risolvere $name in un identificatore canonico (per esempio un percorso assoluto o una
chiave univoca del database) che verrà usato nelle chiamate agli altri metodi del loader, in base al contesto fornito da
$referringName.
public function getReferredName(string $name, string $referringName): string
{
return ...;
}
getUniqueId (string $name): string
Per migliorare le prestazioni Latte usa una cache dei template compilati. Ogni file di template compilato ha bisogno di un nome
univoco derivato dall'identificatore del template sorgente. Questo metodo fornisce una stringa che identifica univocamente
il template $name.
Per i template basati su file può servire allo scopo il percorso assoluto. Per i template in un database è comune una combinazione di un prefisso e dell'ID del record.
public function getUniqueId(string $name): string
{
return ...;
}
Esempio: semplice loader da database
Questo esempio mostra la struttura di base di un loader che carica i template salvati in una tabella di database chiamata
templates, con le colonne name (identificatore univoco), content e
updated_at.
use Latte;
class DatabaseLoader implements Latte\Loader
{
public function __construct(
private \PDO $db,
) {
}
public function getContent(string $name): string
{
$stmt = $this->db->prepare('SELECT content FROM templates WHERE name = ?');
$stmt->execute([$name]);
$content = $stmt->fetchColumn();
if ($content === false) {
throw new Latte\TemplateNotFoundException("Template '$name' non trovato nel database.");
}
return $content;
}
// questo semplice esempio presume che i nomi dei template ('homepage', 'article', ecc.)
// siano ID univoci e che i template non si referenzino a vicenda in modo relativo
public function getReferredName(string $name, string $referringName): string
{
return $name;
}
public function getUniqueId(string $name): string
{
// qui l'uso di un prefisso e del nome stesso è univoco e sufficiente
return 'db_' . $name;
}
}
// uso:
$pdo = new \PDO(/* dati di connessione */);
$loader = new DatabaseLoader($pdo);
$latte->setLoader($loader);
$latte->render('homepage'); // carica dal DB il template chiamato 'homepage'
I loader personalizzati vi danno il pieno controllo sulla provenienza dei vostri template Latte e permettono l'integrazione con i più diversi sistemi di archiviazione e flussi di lavoro.