Pratiques pour les développeurs
Installation
La meilleure façon d'installer Latte est d'utiliser un Composer :
composer require latte/latte
Versions PHP supportées (s'applique aux dernières versions de Latte patch) :
version | compatible avec PHP |
---|---|
PHP 8.0 – 8.2 – Latte 3.0 – PHP 8.0 – 8.2 |
Comment rendre un modèle
Comment rendre un modèle ? Il suffit d'utiliser ce code simple :
$latte = new Latte\Engine;
// répertoire de cache
$latte->setTempDirectory('/path/to/tempdir');
$params = [ /* variables de modèle */ ];
// ou $params = new TemplateParameters(/* ... */);
// rendre vers la sortie
$latte->render('template.latte', $params);
// ou rendu vers la variable
$output = $latte->renderToString('template.latte', $params);
Les paramètres peuvent être des tableaux ou mieux encore des objets, ce qui permettra de vérifier et de suggérer le type dans l'éditeur.
Vous pouvez également trouver des exemples d'utilisation dans le référentiel Latte examples.
Performances et mise en cache
Les modèles Latte sont extrêmement rapides, car Latte les compile directement en code PHP et les met en cache sur le disque. Ainsi, ils n'ont pas de surcharge supplémentaire par rapport aux modèles écrits en PHP pur.
Le cache est automatiquement régénéré chaque fois que vous modifiez le fichier source. Vous pouvez donc facilement modifier vos modèles Latte pendant le développement et voir les changements immédiatement dans le navigateur. Vous pouvez désactiver cette fonction dans un environnement de production et économiser un peu de performance :
$latte->setAutoRefresh(false);
Lorsqu'elle est déployée sur un serveur de production, la génération initiale du cache, en particulier pour les grandes applications, peut naturellement prendre un certain temps. Latte a une prévention intégrée contre la ruée vers le cache. Il s'agit d'une situation où le serveur reçoit un grand nombre de demandes simultanées et, comme le cache de Latte n'existe pas encore, elles le génèrent toutes en même temps. Ce qui fait grimper le CPU en flèche. Latte est intelligent, et lorsqu'il y a plusieurs demandes simultanées, seul le premier thread génère le cache, les autres attendent et l'utilisent ensuite.
Paramètres en tant que classe
Il est préférable de créer une classe plutôt que de transmettre des variables au modèle sous forme de tableaux. Vous obtenez une notation sûre, une suggestion agréable dans l'IDE et un moyen d'enregistrer 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ésactiver l'échappement automatique d'une variable
Si la variable contient une chaîne HTML, vous pouvez la marquer pour que Latte ne l'échappe pas automatiquement (et donc
doublement). Cela évite d'avoir à spécifier |noescape
dans le modèle.
La méthode la plus simple consiste à envelopper 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 donc
créer votre propre classe dont la méthode __toString()
renverra du code HTML qui ne sera pas échappé
automatiquement :
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 fournir l'échappement des paramètres,
sinon une vulnérabilité XSS peut se produire !
Comment étendre Latte avec des filtres, des balises, etc.
Comment ajouter un filtre, une fonction, une balise, etc. personnalisés à Latte ? Découvrez-le dans le chapitre consacré à l'extension de Latte. Si vous voulez réutiliser vos modifications dans différents projets ou si vous voulez les partager avec d'autres, vous devez alors créer une extension.
Tout code dans le modèle {php ...}
Seules les expressions PHP peuvent être écrites à l'intérieur de la balise {do}
Vous ne pouvez donc pas, par exemple, insérer des
constructions comme if ... else
ou des déclarations terminées par un point-virgule.
Cependant, vous pouvez enregistrer l'extension RawPhpExtension
, qui ajoute la balise {php ...}
. Vous
pouvez l'utiliser pour insérer n'importe quel code PHP. Elle n'est soumise à aucune règle du mode “bac à sable”, et son
utilisation relève donc de la responsabilité de l'auteur du modèle.
$latte->addExtension(new Latte\Essential\RawPhpExtension);
Vérification du code généré
Latte compile les modèles en code PHP. Bien sûr, il s'assure que le code généré est syntaxiquement valide. Cependant, lors de l'utilisation d'extensions tierces ou de RawPhpExtension, Latte ne peut pas garantir l'exactitude du fichier généré. De plus, en PHP, vous pouvez écrire du code syntaxiquement correct mais interdit (par exemple, assigner une valeur à la variable $this) et provoquer une erreur de compilation PHP. Si vous écrivez une telle opération dans un modèle, elle sera également incluse dans le code PHP généré. Comme il existe plus de deux cents opérations interdites en PHP, Latte ne cherche pas à les détecter. PHP lui-même les signalera lors du rendu, ce qui ne pose généralement pas de problème.
Cependant, il y a des situations où vous voulez savoir pendant la compilation du modèle qu'il ne contient pas d'erreurs de compilation PHP. En particulier lorsque les modèles peuvent être édités par des utilisateurs, ou que vous utilisez Sandbox. Dans ce cas, faites vérifier les modèles pendant la compilation. Vous pouvez activer cette fonctionnalité en utilisant la méthode Engine::enablePhpLint(). Puisqu'elle doit appeler le binaire 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) {
// attrape les erreurs de latte et aussi les erreurs de compilation en PHP
echo 'Error: ' . $e->getMessage();
}
Locale
Latte vous permet de définir la locale, qui affecte le formatage des nombres, des dates et des tris. Elle est définie à
l'aide de la méthode setLocale()
. L'identifiant de la locale suit la norme de balise de langue de l'IETF, qui
utilise l'extension PHP intl
. Il se compose d'un code de langue et éventuellement d'un 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('cs');
Les paramètres linguistiques affectent les filtres localDate, sort, number et bytes.
Nécessite l'extension PHP intl
. Les paramètres de Latte n'affectent pas les paramètres
linguistiques globaux de PHP.
Mode strict
En mode d'analyse stricte, Latte vérifie l'absence de balises HTML fermantes et désactive l'utilisation de la variable
$this
. Pour l'activer :
$latte = new Latte\Engine;
$latte->setStrictParsing();
Pour générer des modèles avec l'en-tête declare(strict_types=1)
, procédez comme suit :
$latte = new Latte\Engine;
$latte->setStrictTypes();
Traduction dans les modèles
Utilisez l'extension TranslatorExtension
pour ajouter {_...}
, {translate}
et le filtre translate
au modèle. Ils sont utilisés pour traduire
des valeurs ou des parties du modèle dans d'autres langues. Le paramètre est la méthode (appelable en PHP) qui effectue la
traduction :
class MyTranslator
{
public function __construct(private string $lang)
{}
public function translate(string $original): string
{
// créer $translated à partir de $original en fonction de $this->langue
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é au moment de l'exécution lorsque le modèle est rendu. Cependant, Latte peut traduire tous les textes statiques pendant la compilation du modèle. Cela permet de gagner en performance car chaque chaîne n'est traduite qu'une seule fois et la traduction résultante est écrite dans le fichier compilé. Cela crée plusieurs versions compilées du modèle dans le répertoire de cache, une pour chaque langue. Pour ce faire, il suffit de spécifier la langue comme deuxième paramètre :
$extension = new Latte\Essential\TranslatorExtension(
$translator->translate(...),
$lang,
);
Par texte statique, nous entendons, par exemple, {_'hello'}
ou {translate}hello{/translate}
. Le texte
non statique, tel que {_$foo}
, continuera à être traduit au moment de l'exécution.
Le modèle peut également transmettre des paramètres supplémentaires au traducteur via {_$original, foo: bar}
ou {translate foo: bar}
, qu'il reçoit dans le tableau $params
:
public function translate(string $original, ...$params): string
{
// $params['foo'] === 'bar'
}
Débogage et Tracy
Latte essaie de rendre le développement aussi agréable que possible. Pour le débogage, il existe trois balises {dump}
, {debugbreak}
et {trace}
.
Vous obtiendrez plus de confort en installant l'excellent outil de débogage Tracy et en activant le plugin Latte :
// active Tracy
Tracy\Debugger::enable();
$latte = new Latte\Engine;
// active l'extension de Tracy
$latte->addExtension(new Latte\Bridges\Tracy\TracyExtension);
Vous verrez alors toutes les erreurs dans un écran rouge soigné, y compris les erreurs dans les modèles avec mise en évidence des lignes et des colonnes (vidéo). En même temps, dans le coin inférieur droit de la barre Tracy, un onglet pour Latte apparaît, où vous pouvez voir clairement tous les modèles rendus et leurs relations (y compris la possibilité de cliquer dans le modèle ou le code compilé), ainsi que les variables :
Comme Latte compile les modèles en code PHP lisible, vous pouvez facilement les parcourir dans votre IDE.
Linter : Validation de la syntaxe du modèle
L'outil Linter vous aidera à passer en revue tous les modèles et à vérifier les erreurs de syntaxe. Il est lancé à partir de la console :
vendor/bin/latte-lint <path>
Utilisez le paramètre --strict
pour activer le mode strict.
Si vous utilisez des balises personnalisées, créez également votre Linter personnalisé, par exemple
custom-latte-lint
:
#!/usr/bin/env php
<?php
// entrez le chemin d'accès au fichier autoload.php
require __DIR__ . '/vendor/autoload.php';
$path = $argv[1] ?? '.';
$linter = new Latte\Tools\Linter;
$latte = $linter->getEngine();
// ajoutez vos extensions individuelles ici
$latte->addExtension(/* ... */);
$ok = $linter->scanDirectory($path);
exit($ok ? 0 : 1);
Vous pouvez également transmettre votre propre objet Latte\Engine
au Linter :
$latte = new Latte\Engine;
// nous configurons ici l'objet $latte
$linter = new Latte\Tools\Linter(engine: $latte);
Chargement de modèles à partir d'une chaîne
Vous avez besoin de charger des modèles à partir de chaînes de caractères plutôt que de fichiers, peut-être à 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 levées dans {try}
et dans le bac
à sable lui sont transmises.
$loggingHandler = function (Throwable $e, Latte\Runtime\Template $template) use ($logger) {
$logger->log($e);
};
$latte = new Latte\Engine;
$latte->setExceptionHandler($loggingHandler);
Recherche automatique de mise en page
En utilisant la balise {layout}
le modèle détermine son
modèle parent. Il est également possible de faire en sorte que la mise en page soit recherchée automatiquement, ce qui
simplifiera l'écriture des modèles puisqu'ils n'auront pas besoin d'inclure la balise {layout}
.
Cela s'effectue comme suit :
$finder = function (Latte\Runtime\Template $template) {
if (!$template->getReferenceType()) {
// il renvoie le chemin d'accès au fichier modèle parent
return 'automatic.layout.latte';
}
};
$latte = new Latte\Engine;
$latte->addProvider('coreParentFinder', $finder);
Si le modèle ne doit pas avoir de mise en page, il l'indique avec la balise {layout none}
.