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} ou n: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.

version: 3.0