Extension de Latte
Latte est conçu pour être extensible. Bien que son ensemble standard de balises, filtres et fonctions couvre de nombreux cas d'utilisation, vous avez souvent besoin d'ajouter votre propre logique spécifique ou des outils d'aide. Cette page fournit un aperçu des façons d'étendre Latte pour qu'il corresponde parfaitement aux exigences de votre projet – des simples aides aux nouvelles syntaxes complexes.
Méthodes d'extension de Latte
Voici un aperçu rapide des principales façons de personnaliser et d'étendre Latte :
- Filtres personnalisés: Pour formater ou transformer des
données directement dans la sortie du template (par ex.
{$var|myFilter}
). Idéal pour des tâches comme le formatage de dates, la modification de texte ou l'application d'un échappement spécifique. Vous pouvez également les utiliser pour modifier de plus grands blocs de contenu HTML en enveloppant le contenu dans un{block}
anonyme et en lui appliquant un filtre personnalisé. - Fonctions personnalisées: Pour ajouter une logique
réutilisable qui peut être appelée dans les expressions du template (par ex.
{myFunction($arg1, $arg2)}
). Utile pour les calculs, l'accès aux fonctions d'aide de l'application ou la génération de petites parties de contenu. - Balises personnalisées: Pour créer de toutes nouvelles
constructions de langage (
{mytag}...{/mytag}
oun:mytag
). Les balises offrent le plus de possibilités, permettent de définir des structures personnalisées, de contrôler l'analyse syntaxique du template et d'implémenter une logique de rendu complexe. - Passes de compilation: Fonctions qui modifient l'arbre syntaxique abstrait (AST) du template après l'analyse syntaxique, mais avant la génération du code PHP. Elles sont utilisées pour des optimisations avancées, des contrôles de sécurité (comme le Sandbox) ou des modifications automatiques du code.
- Chargeurs personnalisés: Pour changer la façon dont Latte recherche et charge les fichiers de template (par ex. chargement depuis une base de données, un stockage chiffré, etc.).
Choisir la bonne méthode d'extension est crucial. Avant de créer une balise complexe, demandez-vous si un filtre ou une fonction plus simple ne suffirait pas. Illustrons cela avec un exemple : l'implémentation d'un générateur Lorem ipsum qui prend en argument le nombre de mots à générer.
- Comme balise ?
{lipsum 40}
– Possible, mais les balises sont plus adaptées aux structures de contrôle ou à la génération de balises complexes. Les balises ne peuvent pas être utilisées directement dans les expressions. - Comme filtre ?
{=40|lipsum}
– Techniquement, cela fonctionne, mais les filtres sont conçus pour transformer la valeur d'entrée. Ici,40
est un argument, pas une valeur qui est transformée. Cela semble sémantiquement incorrect. - Comme fonction ?
{lipsum(40)}
– C'est la solution la plus naturelle ! Les fonctions acceptent des arguments et retournent des valeurs, ce qui est idéal pour une utilisation dans n'importe quelle expression :{var $text = lipsum(40)}
.
Recommandation générale : Utilisez les fonctions pour les calculs/générations, les filtres pour la transformation et les balises pour les nouvelles constructions de langage ou les balises complexes. Utilisez les passes pour la manipulation de l'AST et les chargeurs pour obtenir les templates.
Enregistrement direct
Pour les outils d'aide spécifiques au projet ou les extensions rapides, Latte permet l'enregistrement direct de filtres et de
fonctions dans l'objet Latte\Engine
.
Pour enregistrer un filtre, utilisez la méthode addFilter()
. Le premier argument de votre fonction de filtre sera
la valeur avant le caractère |
et les arguments suivants sont ceux qui sont passés après les deux-points
:
.
$latte = new Latte\Engine;
// Définition du filtre (objet appelable : fonction, méthode statique, etc.)
$myTruncate = fn(string $s, int $length = 50) => mb_substr($s, 0, $length);
// Enregistrement
$latte->addFilter('truncate', $myTruncate);
// Utilisation dans le template : {$text|truncate} ou {$text|truncate:100}
Vous pouvez également enregistrer un Chargeur de Filtre, une fonction qui fournit dynamiquement des objets appelables de filtres selon le nom requis :
$latte->addFilterLoader(fn(string $name) => /* retourne un objet appelable ou null */);
Pour enregistrer une fonction utilisable dans les expressions du template, utilisez addFunction()
.
$latte = new Latte\Engine;
// Définition de la fonction
$isWeekend = fn(DateTimeInterface $date) => $date->format('N') >= 6;
// Enregistrement
$latte->addFunction('isWeekend', $isWeekend);
// Utilisation dans le template : {if isWeekend($myDate)}Week-end !{/if}
Pour plus d'informations, consultez les sections Création de filtres personnalisés et Fonctions.
Méthode robuste : Extension Latte
Bien que l'enregistrement direct soit simple, la manière standard et recommandée d'emballer et de distribuer les extensions Latte est via les classes Extension. Une Extension sert de point de configuration central pour enregistrer plusieurs balises, filtres, fonctions, passes de compilation et autres éléments.
Pourquoi utiliser les Extensions ?
- Organisation : Maintient les extensions liées (balises, filtres, etc. pour une fonctionnalité spécifique) ensemble dans une seule classe.
- Réutilisabilité et partage : Emballez facilement vos extensions pour les utiliser dans d'autres projets ou pour les partager avec la communauté (par ex. via Composer).
- Pleine puissance : Les balises personnalisées et les passes de compilation ne peuvent être enregistrées que via les Extensions.
Enregistrement d'une Extension
Une Extension est enregistrée dans Latte à l'aide de la méthode addExtension()
(ou via le fichier de configuration) :
$latte = new Latte\Engine;
$latte->addExtension(new MyProjectExtension);
Si vous enregistrez plusieurs extensions et qu'elles définissent des balises, filtres ou fonctions du même nom, la dernière extension ajoutée a la priorité. Cela signifie également que vos extensions peuvent remplacer les balises/filtres/fonctions natifs.
Chaque fois que vous effectuez une modification dans la classe et que le renouvellement automatique n'est pas désactivé, Latte recompilera automatiquement vos templates.
Création d'une Extension
Pour créer votre propre extension, vous devez créer une classe qui hérite de Latte\Extension. Pour avoir une idée de ce à quoi ressemble une telle extension, jetez un œil à la CoreExtension intégrée.
Examinons les méthodes que vous pouvez implémenter :
beforeCompile (Latte\Engine $engine): void
Appelée avant la compilation du template. La méthode peut être utilisée par exemple pour des initialisations liées à la compilation.
getTags(): array
Appelée lors de la compilation du template. Retourne un tableau associatif nom de la balise ⇒ objet appelable, qui sont des fonctions pour analyser les balises. Plus d'informations.
public function getTags(): array
{
return [
'foo' => FooNode::create(...),
'bar' => BarNode::create(...),
'n:baz' => NBazNode::create(...),
// ...
];
}
La balise n:baz
représente un pur n:attribut,
c'est-à-dire une balise qui ne peut être écrite que comme un attribut.
Pour les balises foo
et bar
, Latte reconnaît automatiquement s'il s'agit de balises paires, et si
oui, elles peuvent être automatiquement écrites à l'aide de n:attributs, y compris les variantes avec les préfixes
n:inner-foo
et n:tag-foo
.
L'ordre d'exécution de ces n:attributs est déterminé par leur ordre dans le tableau retourné par la méthode
getTags()
. Ainsi, n:foo
est toujours exécuté avant n:bar
, même si les attributs dans la
balise HTML sont listés dans l'ordre inverse comme <div n:bar="..." n:foo="...">
.
Si vous avez besoin de déterminer l'ordre des n:attributs sur plusieurs extensions, utilisez la méthode d'aide
order()
, où le paramètre before
xor after
spécifie quelles balises sont triées avant ou
après la balise.
public function getTags(): array
{
return [
'foo' => self::order(FooNode::create(...), before: 'bar')]
'bar' => self::order(BarNode::create(...), after: ['block', 'snippet'])]
];
}
getPasses(): array
Appelée lors de la compilation du template. Retourne un tableau associatif nom de la passe ⇒ objet appelable, qui sont des fonctions représentant les passes de compilation, qui parcourent et modifient l'AST.
Ici aussi, la méthode d'aide order()
peut être utilisée. La valeur des paramètres before
ou
after
peut être *
signifiant avant/après tout.
public function getPasses(): array
{
return [
'optimize' => Passes::optimizePass(...),
'sandbox' => self::order($this->sandboxPass(...), before: '*'),
// ...
];
}
beforeRender (Latte\Engine $engine): void
Appelée avant chaque rendu du template. La méthode peut être utilisée par exemple pour initialiser des variables utilisées pendant le rendu.
getFilters(): array
Appelée avant le rendu du template. Retourne les filtres sous forme de tableau associatif nom du filtre ⇒ objet appelable. Plus d'informations.
public function getFilters(): array
{
return [
'batch' => $this->batchFilter(...),
'trim' => $this->trimFilter(...),
// ...
];
}
getFunctions(): array
Appelée avant le rendu du template. Retourne les fonctions sous forme de tableau associatif nom de la fonction ⇒ objet appelable. Plus d'informations.
public function getFunctions(): array
{
return [
'clamp' => $this->clampFunction(...),
'divisibleBy' => $this->divisibleByFunction(...),
// ...
];
}
getProviders(): array
Appelée avant le rendu du template. Retourne un tableau de fournisseurs, qui sont généralement des objets utilisés par les
balises à l'exécution. On y accède via $this->global->...
. Plus d'informations.
public function getProviders(): array
{
return [
'myFoo' => $this->foo,
'myBar' => $this->bar,
// ...
];
}
getCacheKey (Latte\Engine $engine): mixed
Appelée avant le rendu du template. La valeur de retour fait partie de la clé dont le hachage est contenu dans le nom du fichier du template compilé. Pour différentes valeurs de retour, Latte générera donc différents fichiers de cache.