Modèles
Nette utilise le système de modèles Latte. Latte est utilisé parce que c'est le système de modèles le plus sûr pour PHP, et en même temps le système le plus intuitif. Vous n'avez pas besoin d'apprendre grand chose de nouveau, il vous suffit de connaître PHP et quelques balises Latte.
Il est courant que la page soit complétée à partir du modèle de mise en page + le modèle d'action. Voici à quoi peut
ressembler un modèle de mise en page, remarquez les blocs {block}
et la balise {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}My App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
Et ceci pourrait être le modèle d'action :
{block title}Homepage{/block}
{block content}
<h1>Homepage</h1>
...
{/block}
Il définit le bloc content
, qui est inséré à la place de {include content}
dans la mise en page,
et redéfinit également le bloc title
, qui écrase {block title}
dans la mise en page. Essayez
d'imaginer le résultat.
Recherche de modèles
Le chemin vers les modèles est déduit selon une logique simple. Il essaie de voir si l'un de ces fichiers modèles existe par
rapport au répertoire où se trouve la classe du présentateur, où <Presenter>
est le nom du présentateur
actuel et <view>
est le nom de l'action en cours :
templates/<Presenter>/<view>.latte
templates/<Presenter>.<view>.latte
Si le modèle n'est pas trouvé, il essaiera de chercher dans le répertoire templates
au niveau supérieur,
c'est-à-dire au même niveau que le répertoire contenant la classe du présentateur.
Si le modèle n'y est pas trouvé non plus, la réponse est une erreur 404.
Vous pouvez également changer la vue en utilisant $this->setView('otherView')
. Ou, au lieu de chercher,
spécifiez directement le nom du fichier de modèle en utilisant
$this->template->setFile('/path/to/template.latte')
.
Vous pouvez modifier les chemins dans lesquels les modèles sont recherchés en remplaçant la méthode formatTemplateFiles, qui renvoie un tableau de chemins de fichiers possibles.
Le modèle est attendu dans les fichiers suivants :
templates/<Presenter>/@<layout>.latte
templates/<Presenter>.@<layout>.latte
templates/@<layout>.latte
mise en page commune à plusieurs présentateurs
<Presenter>
est le nom du présentateur actuel et <layout>
est le nom de la mise en page,
qui est par défaut 'layout'
. Le nom peut être modifié avec $this->setLayout('otherLayout')
, de
sorte que les fichiers @otherLayout.latte
seront essayés.
Vous pouvez également spécifier directement le nom du fichier du modèle de présentation en utilisant
$this->setLayout('/path/to/template.latte')
. L'utilisation de $this->setLayout(false)
désactivera
la recherche de la mise en page.
Vous pouvez modifier les chemins dans lesquels les modèles sont recherchés en remplaçant la méthode formatLayoutTemplateFiles, qui renvoie un tableau de chemins de fichiers possibles.
Variables dans le modèle
Les variables sont transmises au modèle en les écrivant à $this->template
. Elles sont ensuite disponibles
dans le modèle en tant que variables locales :
$this->template->article = $this->articles->getById($id);
De cette façon, nous pouvons facilement passer n'importe quelle variable aux modèles. Cependant, lors du développement d'applications robustes, il est souvent plus utile de se limiter. Par exemple, en définissant explicitement une liste de variables que le modèle attend et leurs types. Cela permettra à PHP de vérifier le type, à l'IDE d'autocompléter correctement et à l'analyse statique de détecter les erreurs.
Et comment définir une telle énumération ? Tout simplement sous la forme d'une classe et de ses propriétés. Nous la
nommons de façon similaire à 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 autres variables
}
L'objet $this->template
dans le présentateur sera maintenant une instance de la classe
ArticleTemplate
. Ainsi, PHP vérifie les types déclarés lorsqu'ils sont écrits. Et à partir de PHP 8.2, il
préviendra également en cas d'écriture dans une variable inexistante. Dans les versions précédentes, la même chose peut
être réalisée en utilisant le trait Nette\SmartObject.
L'annotation @property-read
est pour les IDE et l'analyse statique, elle fera fonctionner la complétion
automatique, voir PhpStorm et la complétion de
code pour $this->template.

Vous pouvez aussi vous offrir le luxe de chuchoter dans les templates, il suffit d'installer le plugin Latte dans PhpStorm et de spécifier le nom de la classe au début du template, voir l'article Latte : how to type system:
{templateType App\Presenters\ArticleTemplate}
...
C'est également de cette façon que les modèles fonctionnent dans les composants, il suffit de suivre la convention de
nommage et de créer une classe de modèle FifteenTemplate
pour le composant, par exemple
FifteenControl
.
Si vous devez créer un $template
en tant qu'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 présentateurs et les composants transmettent automatiquement plusieurs variables utiles aux modèles :
$basePath
est un chemin URL absolu vers le répertoire racine (par exemple/CD-collection
)$baseUrl
est une URL absolue vers le répertoire racine (par exemplehttp://localhost/CD-collection
)$user
est un objet représentant l'utilisateur$presenter
est le présentateur actuel$control
est le composant ou le présentateur actuel$flashes
liste des messages envoyés par la méthodeflashMessage()
Si vous utilisez une classe de modèle personnalisée, ces variables sont transmises si vous créez une propriété pour elles.
Création de liens
Dans le modèle, nous créons des liens vers d'autres présentateurs et actions comme suit :
<a n:href="Product:show">detail</a>
L'attribut n:href
est très pratique pour les balises HTML <a>
. Si nous voulons imprimer le
lien ailleurs, par exemple dans le texte, nous utilisons {link}
:
URL is: {link Home:default}
Pour plus d'informations, voir Création de liens.
Filtres, balises, etc. personnalisés
Le système de modélisation Latte peut être étendu avec des filtres, des fonctions, des balises, etc. personnalisés. Ceci
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 configurer directement l'objet Latte\Engine
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
Latte version 3 propose un moyen plus avancé en créant une extension pour chaque projet web. Voici un exemple approximatif d'une telle classe :
namespace App\Templating;
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 en utilisant la configuration:
latte:
extensions:
- App\Templating\LatteExtension
Traduction de
Si vous programmez une application multilingue, vous aurez probablement besoin d'éditer une partie du texte du modèle dans
différentes langues. Pour ce faire, le Nette Framework définit une interface de traduction Nette\Localization\Translator, qui possède
une seule méthode translate()
. Celle-ci accepte le message $message
, qui est généralement une chaîne
de caractères, et tout autre paramètre. La tâche consiste à renvoyer la chaîne traduite. Il n'y a pas d'implémentation par
défaut dans Nette, vous pouvez choisir en fonction de vos besoins parmi plusieurs solutions prêtes à l'emploi que vous
trouverez sur Componette. Leur documentation vous indique comment
configurer le traducteur.
Les modèles peuvent être configurés avec un traducteur, que l'on nous aura passé, en utilisant la méthode setTranslator()
:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
Alternativement, le traducteur peut être défini à l'aide de la configuration:
latte:
extensions:
- Latte\Essential\TranslatorExtension
Le traducteur peut alors être utilisé, par exemple, comme un filtre |translate
, avec des paramètres
supplémentaires transmis à la méthode translate()
(voir foo, bar
) :
<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
Ou comme une balise de soulignement :
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Pour la traduction des sections de modèles, il existe une balise appariée {translate}
(depuis Latte 2.11, la
balise {_}
était utilisée auparavant) :
<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>
Translator est appelé par défaut au moment de l'exécution, lors du rendu du modèle. Latte version 3, cependant, peut traduire tout le texte statique 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 modèle 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 :
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Par texte statique, nous entendons, par exemple, {_'hello'}
ou {translate}hello{/translate}
. Le texte
non statique, tel que {_$foo}
, continuera à être compilé à la volée.