Pratiques de développement
Installation
La meilleure façon d'installer Latte est d'utiliser Composer :
composer require latte/latte
Versions PHP supportées (s'applique aux dernières versions mineures de Latte) :
version | compatible avec PHP |
---|---|
Latte 3.0 | PHP 8.0 – 8.2 |
Comment rendre un template
Comment rendre un template ? Il suffit de ce simple code :
$latte = new Latte\Engine;
// répertoire pour le cache
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* variables du template */ ];
// ou $params = new TemplateParameters(/* ... */);
// rend vers la sortie
$latte->render('template.latte', $params);
// rend dans une variable
$output = $latte->renderToString('template.latte', $params);
Les paramètres peuvent être un tableau ou, encore mieux, un objet, qui assure le contrôle de type et l'autocomplétion dans les éditeurs.
Vous trouverez également des exemples d'utilisation dans le dépôt Latte examples.
Performance et cache
Les templates dans Latte sont extrêmement rapides, car Latte les compile directement en code PHP et les stocke dans un cache sur disque. Ils n'ont donc aucune surcharge par rapport aux templates écrits en PHP pur.
Le cache est automatiquement régénéré chaque fois que vous modifiez le fichier source. Ainsi, pendant le développement, vous pouvez confortablement éditer vos templates Latte et voir les changements immédiatement dans le navigateur. Vous pouvez désactiver cette fonctionnalité dans l'environnement de production pour économiser un peu de performance :
$latte->setAutoRefresh(false);
Lors du déploiement sur un serveur de production, la génération initiale du cache, en particulier pour les applications plus importantes, peut bien sûr prendre un certain temps. Latte intègre une prévention contre le cache stampede. Il s'agit d'une situation où un grand nombre de requêtes simultanées arrivent, déclenchant Latte, et comme le cache n'existe pas encore, toutes commenceraient à le générer en même temps. Ce qui surchargerait indûment le serveur. Latte est intelligent et, en cas de requêtes simultanées multiples, seul le premier thread génère le cache, les autres attendent puis l'utilisent.
Paramètres en tant que classe
Plutôt que de passer des variables au template sous forme de tableau, il est préférable de créer une classe. Vous obtiendrez ainsi une écriture typée, une autocomplétion agréable dans l'IDE et un moyen pour l'enregistrement des filtres et des fonctions.
class MailTemplateParameters
{
public function __construct(
public string $lang,
public Address $address,
public string $subject,
public array $items,
public ?float $price = null,
) {}
}
$latte->render('mail.latte', new MailTemplateParameters(
lang: $this->lang,
subject: $title,
price: $this->getPrice(),
items: [],
address: $userAddress,
));
Désactivation de l'échappement automatique des variables
Si une variable contient une chaîne HTML, vous pouvez la marquer pour que Latte ne l'échappe pas automatiquement (et donc
doublement). Vous éviterez ainsi d'avoir à utiliser |noescape
dans le template.
Le moyen le plus simple est d'encapsuler la chaîne dans un objet Latte\Runtime\Html
:
$params = [
'articleBody' => new Latte\Runtime\Html($article->htmlBody),
];
Latte n'échappe pas non plus tous les objets qui implémentent l'interface Latte\HtmlStringable
. Vous pouvez
ainsi créer votre propre classe dont la méthode __toString()
retournera du code HTML qui ne sera pas
automatiquement échappé :
class Emphasis extends Latte\HtmlStringable
{
public function __construct(
private string $str,
) {
}
public function __toString(): string
{
return '<em>' . htmlspecialchars($this->str) . '</em>';
}
}
$params = [
'foo' => new Emphasis('hello'),
];
La méthode __toString
doit retourner du HTML correct et assurer l'échappement des paramètres,
sinon une vulnérabilité XSS peut survenir !
Comment étendre Latte avec des filtres, des balises, etc.
Comment ajouter un filtre, une fonction, une balise personnalisée, etc. à Latte ? C'est ce que traite le chapitre étendre Latte. Si vous souhaitez réutiliser vos modifications dans différents projets ou les partager avec d'autres, vous devriez créer une extension.
Code arbitraire dans le template {php ...}
À l'intérieur de la balise {do}
, seules les expressions PHP
peuvent être écrites, vous ne pouvez donc pas insérer de constructions comme if ... else
ou des instructions
terminées par un point-virgule.
Cependant, vous pouvez enregistrer l'extension RawPhpExtension
, qui ajoute la balise {php ...}
.
Grâce à elle, vous pouvez insérer n'importe quel code PHP. Aucune règle du mode sandbox ne s'applique à elle, son utilisation
relève donc de la responsabilité de l'auteur du template.
$latte->addExtension(new Latte\Essential\RawPhpExtension);
Vérification du code généré
Latte compile les templates en code PHP. Bien sûr, il veille à ce que le code généré soit syntaxiquement valide.
Cependant, lors de l'utilisation d'extensions tierces ou de RawPhpExtension
, Latte ne peut garantir l'exactitude du
fichier généré. Il est également possible d'écrire en PHP du code qui est syntaxiquement correct, mais interdit (par exemple,
l'affectation d'une valeur à la variable $this
) et provoque une erreur de compilation PHP (PHP Compile Error). Si
vous écrivez une telle opération dans un template, elle se retrouvera également dans le code PHP généré. Comme il existe
environ deux cents opérations interdites différentes en PHP, Latte n'a pas l'ambition de les détecter toutes. C'est PHP
lui-même qui les signalera lors du rendu, ce qui n'est généralement pas un problème.
Cependant, il existe des situations où vous voulez savoir dès la compilation du template qu'il ne contient aucune erreur de
compilation PHP. C'est notamment le cas si les templates peuvent être édités par les utilisateurs, ou si vous utilisez Sandbox. Dans ce cas, faites vérifier vos templates dès la compilation. Cette
fonctionnalité est activée par la méthode Engine::enablePhpLint()
. Comme elle nécessite d'appeler l'exécutable
PHP pour la vérification, passez son chemin en paramètre :
$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
try {
$latte->compile('home.latte');
} catch (Latte\CompileException $e) {
// capture les erreurs Latte et aussi les Compile Error en PHP
echo 'Error: ' . $e->getMessage();
}
Paramètres régionaux
Latte permet de définir les paramètres régionaux, qui influencent le formatage des nombres, des dates et le tri. Ils sont
définis à l'aide de la méthode setLocale()
. L'identifiant des paramètres régionaux suit la norme IETF language
tag, utilisée par l'extension PHP intl
. Il se compose du code de langue et éventuellement du code de pays, par
exemple en_US
pour l'anglais aux États-Unis, de_DE
pour l'allemand en Allemagne, etc.
$latte = new Latte\Engine;
$latte->setLocale('fr_FR'); // Exemple pour le français en France
La définition des paramètres régionaux affecte les filtres localDate, sort, number et bytes.
Nécessite l'extension PHP intl
. La configuration dans Latte n'affecte pas les paramètres régionaux
globaux de PHP.
Mode strict
En mode d'analyse strict, Latte vérifie si les balises HTML de fermeture ne manquent pas et interdit également l'utilisation
de la variable $this
. Activez-le comme suit :
$latte = new Latte\Engine;
$latte->setStrictParsing();
Pour générer des templates avec l'en-tête declare(strict_types=1)
, activez-le comme suit :
$latte = new Latte\Engine;
$latte->setStrictTypes();
Traduction dans les templates
Avec l'extension TranslatorExtension
, vous ajoutez au template les balises {_...}
, {translate}
et le filtre translate
. Ils servent à traduire des valeurs ou des
parties du template dans d'autres langues. Comme paramètre, nous spécifions la méthode (PHP callable) effectuant la
traduction :
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// à partir de $original, nous créons $translated selon $this->lang
return $translated;
}
}
$translator = new MyTranslator($lang);
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...), // [$translator, 'translate'] en PHP 8.0
);
$latte->addExtension($extension);
Le traducteur est appelé à l'exécution lors du rendu du template. Cependant, Latte peut traduire tous les textes statiques dès la compilation du template. Cela économise des performances, car chaque chaîne n'est traduite qu'une seule fois et la traduction résultante est écrite dans la forme compilée. Ainsi, dans le répertoire cache, plusieurs versions compilées du template sont créées, une pour chaque langue. Pour cela, il suffit de spécifier la langue comme deuxième paramètre :
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Par texte statique, on entend par exemple {_'hello'}
ou {translate}hello{/translate}
. Les textes non
statiques, comme {_$foo}
, continueront d'être traduits à l'exécution.
Il est également possible de passer des paramètres supplémentaires au traducteur depuis le template en utilisant
{_$original, foo: bar}
ou {translate foo: bar}
, qu'il recevra sous forme de tableau
$params
:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Débogage et Tracy
Latte essaie de rendre votre développement aussi agréable que possible. Directement à des fins de débogage, il existe un
trio de balises {dump}
, {debugbreak}
et {trace}
.
Vous obtiendrez le plus grand confort si vous installez également l'excellent outil de débogage Tracy et activez le plugin pour Latte :
// active Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// active l'extension pour Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Désormais, toutes les erreurs s'afficheront dans un écran rouge clair, y compris les erreurs dans les templates avec mise en évidence de la ligne et de la colonne (vidéo). En même temps, dans le coin inférieur droit, dans ce qu'on appelle la barre Tracy, un onglet pour Latte apparaîtra, où tous les templates rendus et leurs relations mutuelles sont clairement visibles (y compris la possibilité de cliquer pour accéder au template ou au code compilé) ainsi que les variables :

Comme Latte compile les templates en code PHP clair, vous pouvez facilement les parcourir pas à pas dans votre IDE.
Linter : validation de la syntaxe des templates
L'outil Linter vous aide à parcourir tous les templates et à vérifier s'ils contiennent des erreurs de syntaxe. Il se lance depuis la console :
vendor/bin/latte-lint <chemin>
Le paramètre --strict
active le mode strict.
Si vous utilisez des balises personnalisées, créez également votre propre version du Linter, par ex.
custom-latte-lint
:
#!/usr/bin/env php
<?php
// spécifiez le chemin réel vers le fichier autoload.php
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// ajoutez ici vos extensions individuelles
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
Alternativement, vous pouvez passer votre propre objet Latte\Engine
au Linter :
$latte = new Latte\Engine;
// ici nous configurons l'objet $latte
$linter = new Latte\Tools\Linter(engine: $latte);
Chargement de templates depuis une chaîne
Avez-vous besoin de charger des templates à partir de chaînes plutôt que de fichiers, par exemple à des fins de test ? StringLoader vous aidera :
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file', $params);
Gestionnaire d'exceptions
Vous pouvez définir votre propre gestionnaire pour les exceptions attendues. Les exceptions survenant à l'intérieur de {try}
et dans le sandbox lui seront transmises.
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
Recherche automatique de layout
Avec la balise {layout}
, le
template spécifie son template parent. Il est également possible de laisser la recherche du layout se faire automatiquement, ce
qui simplifie l'écriture des templates, car il ne sera pas nécessaire d'y inclure la balise {layout}
.
Cela s'obtient de la manière suivante :
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// retourne le chemin vers le fichier de layout
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Si le template ne doit pas avoir de layout, il l'indique avec la balise {layout none}
.