Modules
Dans Nette, les modules représentent les unités logiques qui composent une application. Ils comprennent des présentateurs, des modèles, éventuellement aussi des composants et des classes de modèles.
Un répertoire pour les présentateurs et un autre pour les modèles ne seraient pas suffisants pour les projets réels. Avoir des dizaines de fichiers dans un seul dossier est pour le moins inorganisé. Comment s'en sortir ? Il suffit de les répartir en sous-répertoires sur le disque et en espaces de noms dans le code. Et c'est exactement ce que font les modules Nette.
Oublions donc le dossier unique pour les présentateurs et les modèles et créons plutôt des modules, par exemple
Admin
et Front
.
app/ ├──Presenters/├── Modules/ ← répertoire avec les modules │ ├── Admin/ ← module Admin │ │ ├── Presenters/ ← ses présentateurs │ │ │ ├── DashboardPresenter.php │ │ │ └── templates/ │ └── Front/ ← module Front │ └── Presenters/ ← ses présentateurs │ └── ...
Cette structure de répertoire sera reflétée par les espaces de noms des classes, ainsi par exemple
DashboardPresenter
sera dans l'espace de noms App\Modules\Admin\Presenters
:
namespace App\Modules\Admin\Presenters;
class DashboardPresenter extends Nette\Application\UI\Presenter
{
// ...
}
Le présentateur Dashboard
dans le module Admin
est référencé dans l'application en utilisant la
notation deux points comme Admin:Dashboard
, et son action default
comme
Admin:Dashboard:default
. Et comment Nette proper sait-elle que Admin:Dashboard
représente la classe
App\Modules\Admin\Presenters\DashboardPresenter
? Cela est déterminé par le mappage dans
la configuration. Ainsi, la structure donnée n'est pas figée et vous pouvez la modifier en fonction de vos besoins.
Les modules peuvent bien sûr contenir tous les éléments autres que les présentateurs et les modèles, tels que les composants, les classes de modèles, etc.
Modules imbriqués
Les modules ne doivent pas uniquement former une structure plate, vous pouvez également créer des sous-modules, par exemple :
app/ ├── Modules/ ← répertoire avec les modules │ ├── Blog/ ← module Blog │ │ ├── Admin/ ← sous-module Admin │ │ │ ├── Presenters/ │ │ │ └── ... │ │ └── Front/ ← sous-module Front │ │ ├── Presenters/ │ │ └── ... │ ├── Forum/ ← module Forum │ │ └── ...
Ainsi, le module Blog
est divisé en sous-modules Admin
et Front
. Là encore, cela se
reflétera dans les espaces de noms, qui seront App\Modules\Blog\Admin\Presenters
etc. Le présentateur
Dashboard
à l'intérieur du sous-module est désigné par Blog:Admin:Dashboard
.
L'imbrication peut aller aussi loin que vous le souhaitez, de sorte que des sous-sous-modules peuvent être créé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
Définit les règles par lesquelles le nom de la classe est dérivé du nom du présentateur. On les inscrit dans la configuration sous la clé application › mapping
.
Commençons par un exemple qui n'utilise pas de modules. Nous voulons simplement que les classes du présentateur aient
l'espace de nom App\Presenters
. Cela signifie qu'un présentateur tel que Home
doit correspondre à la
classe App\Presenters\HomePresenter
. Ceci peut être réalisé par la configuration suivante :
application:
mapping:
*: App\Presenters\*Presenter
Le nom du présentateur est remplacé par l'astérisque dans le masque de classe et le résultat est le nom de la classe. Facile !
Si nous divisons les présentateurs en modules, nous pouvons avoir notre propre mappage pour chaque module :
application:
mapping:
Front: App\Modules\Front\Presenters\*Presenter
Admin: App\Modules\Admin\Presenters\*Presenter
Api: App\Api\*Presenter
Maintenant, le présentateur Front:Home
correspond à la classe
App\Modules\Front\Presenters\HomePresenter
et le présentateur Admin:Dashboard
à la classe
App\Modules\Admin\Presenters\DashboardPresenter
.
Il est plus pratique de créer une règle générale (étoile) pour remplacer les deux premières. L'astérisque supplémentaire sera ajouté au masque de classe uniquement pour le module :
application:
mapping:
*: App\Modules\*\Presenters\*Presenter
Api: App\Api\*Presenter
Mais qu'en est-il si nous utilisons des modules imbriqués et que nous avons un présentateur Admin:User:Edit
?
Dans ce cas, le segment avec un astérisque représentant le module pour chaque niveau est simplement répété et le résultat
est la classe App\Modules\Admin\User\Presenters\EditPresenter
.
Une notation alternative consiste à utiliser un tableau composé de trois segments au lieu d'une chaîne de caractères. Cette notation est équivalente à la précédente :
application:
mapping:
*: [App\Modules, *, Presenters\*Presenter]
La valeur par défaut est *: *Module\*Presenter
.