Création de filtres personnalisés
Les filtres sont des outils puissants pour formater et modifier les données directement dans les templates
Latte. Ils offrent une syntaxe claire, fondée sur la barre verticale (|), pour transformer les variables ou les
résultats d'expressions dans le format de sortie souhaité.
Que sont les filtres ?
Les filtres de Latte sont essentiellement des fonctions PHP conçues pour transformer une valeur d'entrée en une valeur de
sortie. Ils s'appliquent avec la notation à barre verticale (|) à l'intérieur des expressions de template
({...}).
Commodité : les filtres vous permettent d'encapsuler des tâches de formatage courantes (formatage de dates, changement de casse, troncature) ou des manipulations de données dans des unités réutilisables. Au lieu de répéter du code PHP complexe dans vos templates, il suffit d'appliquer un filtre :
{* Au lieu d'un PHP complexe pour tronquer : *}
{$article->text|truncate:100}
{* Au lieu du code de formatage de date : *}
{$event->startTime|date:'Y-m-d H:i'}
{* Application de plusieurs transformations : *}
{$product->name|lower|capitalize}
Lisibilité : les filtres rendent les templates plus propres et davantage centrés sur la présentation, puisque la logique de transformation part dans la définition du filtre.
Sensibilité au contexte : un atout majeur des filtres de Latte est leur capacité à être sensibles au contexte. Un filtre peut donc reconnaître le type de contenu qu'il traite (HTML, JavaScript, texte brut, etc.) et appliquer la logique ou l'échappement adéquats, ce qui est crucial pour la sécurité et l'exactitude, en particulier lors de la génération de HTML.
Intégration avec la logique applicative : comme pour les fonctions personnalisées, le callable PHP derrière un filtre peut être une closure, une méthode statique ou une méthode d'instance. Un filtre peut donc accéder aux services ou aux données de l'application si besoin, même si son but premier reste de transformer la valeur d'entrée.
Par défaut, Latte fournit un riche jeu de filtres standard. Les filtres personnalisés vous permettent d'étendre ce jeu avec les formatages et transformations propres à votre projet.
Si vous devez appliquer une logique reposant sur plusieurs entrées, ou si vous n'avez pas de valeur principale à transformer, une fonction personnalisée conviendra sans doute mieux. Si vous devez générer du balisage complexe ou piloter le flux du template, envisagez une balise personnalisée.
Création et enregistrement de filtres
Il existe plusieurs façons de définir et d'enregistrer des filtres personnalisés dans Latte.
Enregistrement direct via addFilter()
Le moyen le plus simple d'ajouter un filtre est d'utiliser la méthode addFilter() directement sur l'objet
Latte\Engine. Vous indiquez le nom du filtre (tel qu'il sera utilisé dans le template) et le callable PHP
correspondant.
$latte = new Latte\Engine;
// Filtre simple sans arguments
$latte->addFilter('initial', fn(string $s): string => mb_substr($s, 0, 1) . '.');
// Filtre avec un argument optionnel
$latte->addFilter('shortify', function (string $s, int $len = 10): string {
return mb_substr($s, 0, $len);
});
// Filtre traitant un tableau
$latte->addFilter('sum', fn(array $numbers): int|float => array_sum($numbers));
Utilisation dans le template :
{$name|initial} {* Affiche 'J.' si $name vaut 'John' *}
{$description|shortify} {* Utilise la longueur par défaut, 10 *}
{$description|shortify:50} {* Utilise la longueur 50 *}
{$prices|sum} {* Affiche la somme des éléments du tableau $prices *}
Passage des arguments :
La valeur située à gauche de la barre verticale (|) est toujours passée comme premier argument à la
fonction du filtre. Les paramètres indiqués après le deux-points (:) dans le template sont passés comme arguments
suivants.
{$text|shortify:30}
// Appelle la fonction PHP shortify($text, 30)
Enregistrement via une extension
Pour une meilleure organisation, en particulier si vous créez des jeux de filtres réutilisables ou si vous les partagez sous forme de paquets, la manière recommandée est de les enregistrer dans une extension Latte :
namespace App\Templating;
use Latte\Extension;
class MyLatteExtension extends Extension
{
public function getFilters(): array
{
return [
'initial' => $this->initial(...),
'shortify' => $this->shortify(...),
];
}
public function initial(string $s): string
{
return mb_substr($s, 0, 1) . '.';
}
public function shortify(string $s, int $len = 10): string
{
return mb_substr($s, 0, $len);
}
}
// Enregistrement
$latte = new Latte\Engine;
$latte->addExtension(new MyLatteExtension);
Cette approche garde la logique de vos filtres encapsulée et rend l'enregistrement limpide.
Filtres utilisant une classe avec attributs
Une autre façon élégante de définir des filtres consiste à utiliser des méthodes de votre classe de paramètres de template. Il suffit
d'ajouter l'attribut #[Latte\Attributes\TemplateFilter] à la méthode.
use Latte\Attributes\TemplateFilter;
class TemplateParameters
{
public function __construct(
public string $description,
// autres paramètres...
) {}
#[TemplateFilter]
public function shortify(string $s, int $len = 10): string
{
return mb_substr($s, 0, $len);
}
}
// Passage de l'objet au template
$params = new TemplateParameters(description: '...');
$latte->render('template.latte', $params);
Latte détecte et enregistre automatiquement les méthodes marquées par cet attribut lorsque l'objet
TemplateParameters est passé au template. Le nom du filtre dans le template est celui de la méthode
(shortify, ici).
{* Utilisation du filtre défini dans la classe de paramètres *}
{$description|shortify:50}
Filtres contextuels
Il arrive qu'un filtre ait besoin de plus que la seule valeur d'entrée. Il peut lui falloir connaître le type de contenu de la chaîne qu'il traite (HTML, JavaScript, texte brut) ou même le modifier. C'est là qu'entrent en scène les filtres contextuels.
Un filtre contextuel se définit comme un filtre ordinaire, à ceci près que son premier paramètre doit être typé
Latte\Runtime\FilterInfo. Latte reconnaît automatiquement cette signature et passe l'objet FilterInfo
lors de l'appel du filtre. Les paramètres suivants reçoivent les arguments du filtre comme d'habitude.
use Latte\Runtime\FilterInfo;
use Latte\ContentType;
$latte->addFilter('money', function (FilterInfo $info, float $amount): string {
// 1. Vérifiez le type de contenu d'entrée (facultatif, mais recommandé)
// Autorisez null (entrée variable) ou du texte brut. Refusez s'il est appliqué à du HTML, etc.
if (!in_array($info->contentType, [null, ContentType::Text], true)) {
$actualType = $info->contentType ?? 'mixed';
throw new \RuntimeException(
"Filter |money used in incompatible content type $actualType. Expected text or null."
);
}
// 2. Effectuez la transformation
$formatted = number_format($amount, 2, '.', ',') . ' EUR';
$htmlOutput = '<i>' . htmlspecialchars($formatted) . '</i>'; // Assurez un échappement correct !
// 3. Déclarez le type de contenu de sortie
$info->contentType = ContentType::Html;
// 4. Retournez le résultat
return $htmlOutput;
});
$info->contentType est une constante de type chaîne issue de Latte\ContentType (par ex.
ContentType::Html, ContentType::Text, ContentType::JavaScript, etc.), ou null
si le filtre est appliqué à une variable ({$var|filter}). Vous pouvez la lire pour vérifier le contexte
d'entrée et y écrire pour déclarer le type du contexte de sortie.
En fixant le type de contenu à HTML, vous indiquez à Latte que la chaîne retournée par votre filtre est du HTML sûr. Latte n'appliquera alors pas son échappement automatique à ce résultat. C'est capital si votre filtre génère du balisage HTML.
Si votre filtre génère du HTML, c'est à vous d'échapper correctement toutes les données d'entrée
utilisées dans ce HTML (comme dans l'appel htmlspecialchars($formatted) ci-dessus). L'oublier peut créer des
vulnérabilités XSS. Si votre filtre ne retourne que du texte brut, vous n'avez pas besoin de définir
$info->contentType.
Filtres sur les blocs
Les filtres appliqués aux blocs dont le type de contenu n'est pas du texte (typiquement du HTML) doivent être contextuels, car le contenu du bloc a un type de contenu défini dont le filtre doit avoir connaissance. Un filtre classique, non contextuel, ne peut être appliqué qu'à un bloc dont le contenu est du texte brut.
{block heading|money}1000{/block}
{* Le filtre 'money' reçoit '1000' comme deuxième argument
et $info->contentType vaudra ContentType::Html *}
Les filtres contextuels offrent un contrôle puissant sur la façon dont les données sont traitées selon leur contexte : ils rendent possibles des fonctionnalités avancées et garantissent un échappement correct, en particulier lors de la génération de contenu HTML.