Templates
Nette utilise le système de templates Latte. D'une part parce que c'est le système de templates le plus sécurisé pour PHP, et d'autre part parce que c'est aussi le système le plus intuitif. Vous n'avez pas besoin d'apprendre beaucoup de nouveautés, la connaissance de PHP et de quelques balises suffit.
Il est courant qu'une page soit composée d'un template de layout + du template de l'action donnée. Voici à quoi peut
ressembler un template de layout, remarquez les blocs {block}
et la balise {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}Mon App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
Et voici ce que sera le template de l'action :
{block title}Page d'accueil{/block}
{block content}
<h1>Page d'accueil</h1>
...
{/block}
Il définit le bloc content
, qui sera inséré à la place de {include content}
dans le layout, et
redéfinit également le bloc title
, qui écrasera {block title}
dans le layout. Essayez d'imaginer le
résultat.
Recherche de templates
Vous n'avez pas besoin de spécifier dans les presenters quel template doit être rendu, le framework déduit le chemin lui-même et vous évite d'écrire.
Si vous utilisez une structure de répertoires où chaque presenter a son propre répertoire, placez simplement le template
dans ce répertoire sous le nom de l'action (ou de la vue), c'est-à-dire pour l'action default
, utilisez le template
default.latte
:
app/ └── Presentation/ └── Home/ ├── HomePresenter.php └── default.latte
Si vous utilisez une structure où les presenters sont regroupés dans un seul répertoire et les templates dans un dossier
templates
, enregistrez-le soit dans le fichier <Presenter>.<view>.latte
soit
<Presenter>/<view>.latte
:
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── Home.default.latte ← 1ère variante └── Home/ └── default.latte ← 2ème variante
Le répertoire templates
peut également être placé un niveau plus haut, c'est-à-dire au même niveau que le
répertoire contenant les classes des presenters.
Si le template n'est pas trouvé, le presenter répondra par une erreur 404 – page non trouvée.
Vous pouvez changer la vue en utilisant $this->setView('autreVue')
. Il est également possible de spécifier
directement le fichier de template en utilisant $this->template->setFile('/chemin/vers/template.latte')
.
Les fichiers où les templates sont recherchés peuvent être modifiés en surchargeant la méthode formatTemplateFiles(), qui retourne un tableau de noms de fichiers possibles.
Recherche du template de layout
Nette recherche également automatiquement le fichier de layout.
Si vous utilisez une structure de répertoires où chaque presenter a son propre répertoire, placez le layout soit dans le dossier du presenter s'il lui est spécifique, soit un niveau plus haut s'il est commun à plusieurs presenters :
app/ └── Presentation/ ├── @layout.latte ← layout commun └── Home/ ├── @layout.latte ← uniquement pour le presenter Home ├── HomePresenter.php └── default.latte
Si vous utilisez une structure où les presenters sont regroupés dans un seul répertoire et les templates dans un dossier
templates
, le layout sera attendu à ces endroits :
app/ └── Presenters/ ├── HomePresenter.php └── templates/ ├── @layout.latte ← layout commun ├── Home.@layout.latte ← uniquement pour Home, 1ère variante └── Home/ └── @layout.latte ← uniquement pour Home, 2ème variante
Si le presenter se trouve dans un module, la recherche s'effectuera également aux niveaux de répertoires supérieurs, en fonction de l'imbrication du module.
Le nom du layout peut être modifié à l'aide de $this->setLayout('layoutAdmin')
et il sera alors attendu dans
le fichier @layoutAdmin.latte
. Il est également possible de spécifier directement le fichier de template de layout
à l'aide de $this->setLayout('/chemin/vers/template.latte')
.
En utilisant $this->setLayout(false)
ou la balise {layout none}
à l'intérieur du template, la
recherche de layout est désactivée.
Les fichiers où les templates de layout sont recherchés peuvent être modifiés en surchargeant la méthode formatLayoutTemplateFiles(), qui retourne un tableau de noms de fichiers possibles.
Variables dans le template
Nous passons des variables au template en les écrivant dans $this->template
et elles sont ensuite disponibles
dans le template comme variables locales :
$this->template->article = $this->articles->getById($id);
Nous pouvons ainsi passer facilement n'importe quelle variable aux templates. Cependant, lors du développement d'applications robustes, il est plus utile de se limiter. Par exemple, en définissant explicitement la liste des variables que le template attend et leurs types. Grâce à cela, PHP pourra vérifier les types, l'IDE pourra suggérer correctement et l'analyse statique pourra détecter les erreurs.
Et comment définir une telle liste ? Simplement sous la forme d'une classe et de ses propriétés. Nous la nommerons de
manière similaire au presenter, mais avec Template
à la fin :
/**
* @property-read ArticleTemplate $template
*/
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}
class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
public Model\Article $article;
public Nette\Security\User $user;
// et d'autres variables
}
L'objet $this->template
dans le presenter sera désormais une instance de la classe
ArticleTemplate
. Ainsi, PHP vérifiera les types déclarés lors de l'écriture. Et à partir de PHP 8.2, il avertira
également en cas d'écriture dans une variable inexistante ; dans les versions précédentes, le même résultat peut être
obtenu en utilisant le trait Nette\SmartObject.
L'annotation @property-read
est destinée à l'IDE et à l'analyse statique, grâce à elle, l'autocomplétion
fonctionnera, voir PhpStorm et
l'autocomplétion pour $this->template.

Vous pouvez également profiter du luxe de l'autocomplétion dans les templates, il suffit d'installer le plugin pour Latte dans PhpStorm et d'indiquer le nom de la classe au début du template, plus d'informations dans l'article Latte : comment gérer le système de types :
{templateType App\Presentation\Article\ArticleTemplate}
...
C'est ainsi que fonctionnent également les templates dans les composants, il suffit de respecter la convention de nommage et
pour un composant par ex. FifteenControl
créer une classe de template FifteenTemplate
.
Si vous avez besoin de créer $template
comme instance d'une autre classe, utilisez la méthode
createTemplate()
:
public function renderDefault(): void
{
$template = $this->createTemplate(SpecialTemplate::class);
$template->foo = 123;
// ...
$this->sendTemplate($template);
}
Variables par défaut
Les presenters et les composants transmettent automatiquement plusieurs variables utiles aux templates :
$basePath
est le chemin URL absolu vers le répertoire racine (par ex./eshop
)$baseUrl
est l'URL absolue vers le répertoire racine (par ex.http://localhost/eshop
)$user
est l'objet représentant l'utilisateur$presenter
est le presenter actuel$control
est le composant ou presenter actuel$flashes
tableau des messages envoyés par la fonctionflashMessage()
Si vous utilisez votre propre classe de template, ces variables seront transmises si vous créez une propriété pour elles.
Création de liens
Dans le template, les liens vers d'autres presenters & actions sont créés de cette manière :
<a n:href="Product:show">détail du produit</a>
L'attribut n:href
est très pratique pour les balises HTML <a>
. Si nous voulons afficher le
lien ailleurs, par exemple dans du texte, nous utilisons {link}
:
L'adresse est : {link Home:default}
Plus d'informations peuvent être trouvées dans le chapitre Création de liens URL.
Filtres personnalisés, balises, etc.
Le système de templates Latte peut être étendu avec des filtres, fonctions, balises personnalisés, etc. Cela peut être
fait directement dans la méthode render<View>
ou beforeRender()
:
public function beforeRender(): void
{
// ajout d'un filtre
$this->template->addFilter('foo', /* ... */);
// ou nous configurons directement l'objet Latte\Engine
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
Latte version 3 offre une méthode plus avancée, à savoir la création d'une extension pour chaque projet web. Exemple succinct d'une telle classe :
namespace App\Presentation\Accessory;
final class LatteExtension extends Latte\Extension
{
public function __construct(
private App\Model\Facade $facade,
private Nette\Security\User $user,
// ...
) {
}
public function getFilters(): array
{
return [
'timeAgoInWords' => $this->filterTimeAgoInWords(...),
'money' => $this->filterMoney(...),
// ...
];
}
public function getFunctions(): array
{
return [
'canEditArticle' =>
fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
// ...
];
}
// ...
}
Nous l'enregistrons à l'aide de la configuration :
latte:
extensions:
- App\Presentation\Accessory\LatteExtension
Traduction
Si vous programmez une application multilingue, vous aurez probablement besoin d'afficher certains textes dans le template dans
différentes langues. Nette Framework définit à cet effet une interface pour la traduction Nette\Localization\Translator, qui a une seule
méthode translate()
. Elle accepte un message $message
, qui est généralement une chaîne, et tout
autre paramètre. La tâche est de retourner la chaîne traduite. Il n'y a pas d'implémentation par défaut dans Nette, vous
pouvez choisir parmi plusieurs solutions prêtes à l'emploi selon vos besoins, que vous trouverez sur Componette. Dans leur documentation, vous apprendrez comment configurer le
traducteur.
Il est possible de définir un traducteur pour les templates, que nous recevrons via injection, avec la méthode
setTranslator()
:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
Le traducteur peut alternativement être défini via la configuration :
latte:
extensions:
- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)
Ensuite, le traducteur peut être utilisé par exemple comme filtre |translate
, y compris avec des paramètres
supplémentaires qui sont passés à la méthode translate()
(voir foo, bar
) :
<a href="basket">{='Panier'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
Ou comme balise soulignée :
<a href="basket">{_'Panier'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Pour traduire une section du template, il existe une balise paire {translate}
(depuis Latte 2.11, auparavant la
balise {_}
était utilisée) :
<a href="order">{translate}Commande{/translate}</a>
<a href="order">{translate foo, bar}Commande{/translate}</a>
Le traducteur est appelé par défaut à l'exécution lors du rendu du template. Cependant, Latte version 3 peut traduire tous les textes statiques déjà pendant 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, plusieurs versions compilées du template sont créées dans le répertoire cache, une pour chaque langue. Pour cela, il suffit d'indiquer la langue comme deuxième paramètre :
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Par texte statique, on entend par exemple {_'hello'}
ou {translate}hello{/translate}
. Les textes non
statiques, comme par exemple {_$foo}
, continueront d'être traduits à l'exécution.