Moduli
In Nette, i moduli rappresentano le unità logiche che compongono un'applicazione. Comprendono presentatori, modelli, eventualmente anche componenti e classi di modelli.
Una cartella per i presentatori e una per i modelli non sarebbe sufficiente per i progetti reali. Avere decine di file in una cartella è quantomeno disorganizzato. Come uscirne? Semplicemente dividendoli in sottodirectory su disco e in spazi dei nomi nel codice. E questo è esattamente ciò che fanno i moduli Nette.
Dimentichiamo quindi un'unica cartella per i presentatori e i modelli e creiamo invece dei moduli, ad esempio
Admin
e Front
.
app/ ├──Presenters/├── Modules/ ← directory with modules │ ├── Admin/ ← module Admin │ │ ├── Presenters/ ← its presenters │ │ │ ├── DashboardPresenter.php │ │ │ └── templates/ │ └── Front/ ← module Front │ └── Presenters/ ← its presenters │ └── ...
Questa struttura di cartelle si rifletterà negli spazi dei nomi delle classi, quindi ad esempio
DashboardPresenter
sarà nello spazio dei nomi App\Modules\Admin\Presenters
:
namespace App\Modules\Admin\Presenters;
class DashboardPresenter extends Nette\Application\UI\Presenter
{
// ...
}
Il presentatore Dashboard
all'interno del modulo Admin
è referenziato all'interno dell'applicazione
usando la notazione dei due punti come Admin:Dashboard
, e la sua azione default
come
Admin:Dashboard:default
. E come fa Nette a sapere che Admin:Dashboard
rappresenta la classe
App\Modules\Admin\Presenters\DashboardPresenter
? Questo è determinato dalla mappatura
nella configurazione. Pertanto, la struttura data non è rigida e può essere modificata in base alle proprie esigenze.
I moduli possono naturalmente contenere tutti gli altri elementi oltre ai presentatori e ai modelli, come componenti, classi di modelli, ecc.
Moduli annidati
I moduli non devono formare solo una struttura piatta, ma si possono anche creare sottomoduli, ad esempio:
app/ ├── Modules/ ← directory with modules │ ├── Blog/ ← module Blog │ │ ├── Admin/ ← submodule Admin │ │ │ ├── Presenters/ │ │ │ └── ... │ │ └── Front/ ← submodule Front │ │ ├── Presenters/ │ │ └── ... │ ├── Forum/ ← module Forum │ │ └── ...
Così, il modulo Blog
è suddiviso nei sottomoduli Admin
e Front
. Anche in questo caso,
ciò si rifletterà negli spazi dei nomi, che saranno App\Modules\Blog\Admin\Presenters
e così via. Il presentatore
Dashboard
all'interno del sottomodulo viene chiamato Blog:Admin:Dashboard
.
L'annidamento può andare in profondità quanto si vuole, quindi si possono creare dei sottomoduli.
Creazione di collegamenti
I collegamenti nei modelli di presentatore sono relativi al modulo corrente. Pertanto, il collegamento
Foo:default
porta al presentatore Foo
nello stesso modulo del presentatore corrente. Se il modulo
corrente è Front
, ad esempio, il collegamento si presenta in questo modo:
<a n:href="Product:show">link to Front:Product:show</a>
Un collegamento è relativo anche se include il nome di un modulo, che viene considerato un sottomodulo:
<a n:href="Shop:Product:show">link to Front:Shop:Product:show</a>
I collegamenti assoluti sono scritti in modo analogo ai percorsi assoluti su disco, ma con i due punti al posto degli slash. Pertanto, un collegamento assoluto inizia con i due punti:
<a n:href=":Admin:Product:show">link to Admin:Product:show</a>
Per scoprire se ci troviamo in un certo modulo o in un suo sottomodulo possiamo usare la funzione
isModuleCurrent(moduleName)
.
<li n:class="isModuleCurrent('MyEshop:Users') ? active">
<a n:href="Product:">...</a>
</li>
Instradamento
Vedere il capitolo sull'instradamento.
Mappatura
Definisce le regole con cui il nome della classe viene derivato dal nome del presentatore. Vengono scritte nella configurazione sotto la chiave
application › mapping
.
Cominciamo con un esempio che non usa moduli. Vogliamo solo che le classi del presentatore abbiano lo spazio dei nomi
App\Presenters
. Ciò significa che un presentatore come Home
deve mappare alla classe
App\Presenters\HomePresenter
. Questo si può ottenere con la seguente configurazione:
application:
mapping:
*: App\Presenters\*Presenter
Il nome del presentatore viene sostituito con l'asterisco nella maschera della classe e il risultato è il nome della classe. Facile!
Se dividiamo i presentatori in moduli, possiamo avere la nostra mappatura per ogni modulo:
application:
mapping:
Front: App\Modules\Front\Presenters\*Presenter
Admin: App\Modules\Admin\Presenters\*Presenter
Api: App\Api\*Presenter
Ora il presentatore Front:Home
mappa alla classe App\Modules\Front\Presenters\HomePresenter
e il
presentatore Admin:Dashboard
alla classe App\Modules\Admin\Presenters\DashboardPresenter
.
È più pratico creare una regola generale (asterisco) per sostituire le prime due. L'asterisco in più sarà aggiunto alla maschera di classe solo per il modulo:
application:
mapping:
*: App\Modules\*\Presenters\*Presenter
Api: App\Api\*Presenter
Ma cosa succede se utilizziamo moduli annidati e abbiamo un presentatore Admin:User:Edit
? In questo caso, il
segmento con l'asterisco che rappresenta il modulo per ogni livello viene semplicemente ripetuto e il risultato è la classe
App\Modules\Admin\User\Presenters\EditPresenter
.
Una notazione alternativa consiste nell'utilizzare un array composto da tre segmenti invece di una stringa. Questa notazione è equivalente alla precedente:
application:
mapping:
*: [App\Modules, *, Presenters\*Presenter]
Il valore predefinito è *: *Module\*Presenter
.