Modules
Les modules apportent de la clarté aux applications Nette en facilitant la division en unités logiques.
À l'instar de l'organisation des fichiers en dossiers sur un disque dur, Nette permet de diviser les présentateurs, les modèles et les autres classes auxiliaires en modules. Comment cela fonctionne-t-il en pratique ? Simplement en incorporant de nouveaux sous-répertoires dans la structure. Voici un exemple de structure avec deux modules, Front et Admin :
app/ ├── UI/ │ ├── Admin/ ← Admin module │ │ ├── @layout.latte │ │ ├── Dashboard/ │ │ │ ├── DashboardPresenter.php │ │ │ └── default.latte │ │ └── ... │ ├── Front/ ← Front module │ │ ├── @layout.latte │ │ ├── Home/ │ │ │ ├── HomePresenter.php │ │ │ └── default.latte │ │ └── ...
Cette structure de répertoires se reflète dans les espaces de noms des classes. Ainsi, par exemple,
DashboardPresenter
est situé dans l'espace de noms App\UI\Admin\Dashboard
:
namespace App\UI\Admin\Dashboard;
class DashboardPresenter extends Nette\Application\UI\Presenter
{
// ...
}
Dans l'application, nous faisons référence au présentateur Dashboard
dans le module Admin
en
utilisant la notation des deux points comme Admin:Dashboard
. Pour son action default
, nous l'appelons
Admin:Dashboard:default
.
La structure présentée n'est pas rigide ; vous pouvez l'adapter entièrement à vos besoins dans la configuration.
Les modules peuvent inclure tous les autres fichiers, tels que les composants et les classes auxiliaires, en plus des
présentateurs et des modèles. Si vous vous demandez où placer ces derniers, envisagez d'utiliser un dossier
Accessory
:
app/ ├── UI/ │ ├── Admin/ │ │ ├── Accessory/ │ │ │ ├── FormFactory.php │ │ │ └── AdminLayout.php │ │ ├── Dashboard/ │ │ └── ...
Modules imbriqués
Les modules peuvent avoir plusieurs niveaux d'imbrication, comme la structure d'un répertoire sur un disque :
app/ ├── UI/ │ ├── Blog/ ← Blog module │ │ ├── Admin/ ← Admin submodule │ │ │ ├── Dashboard/ │ │ │ └── ... │ │ ├── Front/ ← Front submodule │ │ │ ├── @layout.latte │ │ │ ├── Home/ │ │ │ └── ... │ ├── Forum/ ← Forum module │ │ └── ...
Le module Blog
est divisé en sous-modules Admin
et Front
. Cela se reflète également
dans les espaces de noms, qui apparaissent alors comme App\UI\Blog\Admin
et similaires. Pour désigner le
présentateur Dashboard
au sein du sous-module Admin
, nous l'appelons
Blog:Admin:Dashboard
.
L'imbrication peut être aussi poussée que nécessaire, ce qui permet de créer des sous-sous-modules.
Par exemple, si dans l'administration vous avez de nombreux présentateurs liés à la gestion des commandes, tels que
OrderDetail
, OrderEdit
, OrderDispatch
, etc., vous pouvez créer un module
Order
dans lequel les présentateurs tels que Detail
, Edit
, Dispatch
, et
d'autres seront organisés.
Création de liens
Les liens dans les modèles de présentateur sont relatifs au module actuel. Ainsi, le lien Foo:default
mène au
présentateur Foo
dans le même module que le présentateur actuel. Si le module actuel est Front
, par
exemple, le lien est le suivant :
<a n:href="Product:show">link to Front:Product:show</a>
Un lien est relatif même s'il inclut le nom d'un module, qui est alors considéré comme un sous-module :
<a n:href="Shop:Product:show">link to Front:Shop:Product:show</a>
Les liens absolus sont écrits de manière analogue aux chemins absolus sur le disque, mais avec des deux-points à la place des barres obliques. Ainsi, un lien absolu commence par un deux-points :
<a n:href=":Admin:Product:show">link to Admin:Product:show</a>
Pour savoir si nous sommes dans un certain module ou son sous-module, nous pouvons utiliser la fonction
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('MyEshop:Users') ? active">
<a n:href="Product:">...</a>
</li>
Acheminement
Voir le chapitre sur le routage.
Cartographie
Le mappage définit les règles permettant de dériver le nom de la classe à partir du nom du présentateur. Ces règles sont
spécifiées dans la configuration sous la clé
application › mapping
.
Les structures de répertoire mentionnées plus haut sur cette page sont basées sur la correspondance suivante :
application:
mapping: App\UI\*\**Presenter
Comment fonctionne la cartographie ? Pour mieux comprendre, imaginons d'abord une application sans modules. Nous voulons que
les classes de présentateurs relèvent de l'espace de noms App\UI
, de sorte que le présentateur Home
soit associé à la classe App\UI\HomePresenter
. Cette configuration permet d'atteindre cet objectif :
application:
mapping: App\UI\*Presenter
Ce mappage fonctionne en remplaçant l'astérisque du masque App\UI\*Presenter
par le nom du présentateur
Home
, ce qui donne le nom de classe final App\UI\HomePresenter
. C'est simple !
Cependant, comme vous pouvez le voir dans les exemples de ce chapitre et d'autres chapitres, nous plaçons les classes de
présentateurs dans des sous-répertoires éponymes, par exemple, le présentateur Home
est associé à la classe
App\UI\Home\HomePresenter
. Pour ce faire, il suffit de doubler l'astérisque (Nette Application 3.2 requise) :
application:
mapping: App\UI\**Presenter
Passons maintenant au mappage des présentateurs dans les modules. Nous pouvons définir des correspondances spécifiques pour chaque module :
application:
mapping:
Front: App\UI\Front\**Presenter
Admin: App\UI\Admin\**Presenter
Api: App\Api\*Presenter
Selon cette configuration, le présentateur Front:Home
correspond à la classe
App\UI\Front\Home\HomePresenter
, tandis que le présentateur Api:OAuth
correspond à la classe
App\Api\OAuthPresenter
.
Étant donné que les modules Front
et Admin
ont une approche de mappage similaire et qu'il est
probable qu'il y ait d'autres modules de ce type, il est possible de créer une règle générale qui les remplace. Un nouvel
astérisque pour le module est ajouté au masque de classe :
application:
mapping:
*: App\UI\*\**Presenter
Api: App\Api\*Presenter
Pour les modules imbriqués à plusieurs niveaux, tels que le présentateur Admin:User:Edit
, le segment
astérisque se répète pour chaque niveau, ce qui donne la classe App\UI\Admin\User\Edit\EditPresenter
.
Une autre notation consiste à utiliser un tableau composé de trois segments au lieu d'une chaîne. Cette notation est équivalente à la précédente :
application:
mapping:
*: [App\UI, *, **Presenter]
Api: [App\Api, '', *Presenter]
Si nous n'avons qu'une seule règle dans la configuration, la règle générale, nous pouvons l'écrire brièvement :
application:
mapping: App\UI\*\**Presenter