Moduli
I moduli conferiscono chiarezza alle applicazioni Nette, facilitando la suddivisione in unità logiche.
Analogamente all'organizzazione dei file in cartelle su un disco rigido, in Nette possiamo dividere presentatori, modelli e altre classi ausiliarie in moduli. Come funziona in pratica? Semplicemente incorporando nuove sottodirectory nella struttura. Ecco un esempio di struttura con due moduli, Front e Admin:
app/ ├── UI/ │ ├── Admin/ ← Admin module │ │ ├── @layout.latte │ │ ├── Dashboard/ │ │ │ ├── DashboardPresenter.php │ │ │ └── default.latte │ │ └── ... │ ├── Front/ ← Front module │ │ ├── @layout.latte │ │ ├── Home/ │ │ │ ├── HomePresenter.php │ │ │ └── default.latte │ │ └── ...
Questa struttura di directory si riflette negli spazi dei nomi delle classi, per cui, ad esempio,
DashboardPresenter
si trova nello spazio dei nomi App\UI\Admin\Dashboard
:
namespace App\UI\Admin\Dashboard;
class DashboardPresenter extends Nette\Application\UI\Presenter
{
// ...
}
Nell'applicazione, ci si riferisce al presentatore Dashboard
all'interno del modulo Admin
usando la
notazione dei due punti come Admin:Dashboard
. Per l'azione default
, ci si riferisce ad essa come
Admin:Dashboard:default
.
La struttura presentata non è rigida; è possibile personalizzarla completamente in base alle proprie esigenze nella configurazione.
I moduli possono includere tutti gli altri file, come i componenti e le classi ausiliarie, oltre ai presentatori e ai
modelli. Se si sta valutando dove collocare questi ultimi, si può prendere in considerazione l'uso di una cartella
Accessory
:
app/ ├── UI/ │ ├── Admin/ │ │ ├── Accessory/ │ │ │ ├── FormFactory.php │ │ │ └── AdminLayout.php │ │ ├── Dashboard/ │ │ └── ...
Moduli annidati
I moduli possono avere più livelli di annidamento, simili a una struttura di directory su disco:
app/ ├── UI/ │ ├── Blog/ ← Blog module │ │ ├── Admin/ ← Admin submodule │ │ │ ├── Dashboard/ │ │ │ └── ... │ │ ├── Front/ ← Front submodule │ │ │ ├── @layout.latte │ │ │ ├── Home/ │ │ │ └── ... │ ├── Forum/ ← Forum module │ │ └── ...
Il modulo Blog
è diviso nei sottomoduli Admin
e Front
. Questo si riflette anche negli
spazi dei nomi, che appaiono come App\UI\Blog\Admin
e simili. Per riferirsi al presentatore Dashboard
all'interno del sottomodulo Admin
, ci si riferisce ad esso come Blog:Admin:Dashboard
.
L'annidamento può essere profondo quanto necessario, consentendo la creazione di sottomoduli.
Ad esempio, se nell'amministrazione sono presenti molti presentatori relativi alla gestione degli ordini, come
OrderDetail
, OrderEdit
, OrderDispatch
, ecc. si può creare un modulo Order
in
cui saranno organizzati presentatori come Detail
, Edit
, Dispatch
, e altri.
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
La mappatura definisce le regole per derivare il nome della classe dal nome del presentatore. Queste regole sono specificate
nella configurazione sotto la chiave
application › mapping
.
Le strutture di directory menzionate in precedenza in questa pagina si basano sulla seguente mappatura:
application:
mapping: App\UI\*\**Presenter
Come funziona la mappatura? Per capire meglio, immaginiamo prima un'applicazione senza moduli. Vogliamo che le classi del
presentatore rientrino nello spazio dei nomi App\UI
, in modo che il presentatore Home
sia mappato nella
classe App\UI\HomePresenter
. Ciò può essere ottenuto con questa configurazione:
application:
mapping: App\UI\*Presenter
Questa mappatura funziona sostituendo l'asterisco nella maschera App\UI\*Presenter
con il nome del presenter
Home
, ottenendo il nome finale della classe App\UI\HomePresenter
. Semplice!
Tuttavia, come si può vedere negli esempi di questo e di altri capitoli, le classi dei presentatori sono collocate in
sottodirectory eponime, ad esempio il presentatore Home
è mappato nella classe
App\UI\Home\HomePresenter
. Questo si ottiene raddoppiando l'asterisco (richiede Nette Application 3.2):
application:
mapping: App\UI\**Presenter
Passiamo ora alla mappatura dei presentatori nei moduli. Possiamo definire mappature specifiche per ogni modulo:
application:
mapping:
Front: App\UI\Front\**Presenter
Admin: App\UI\Admin\**Presenter
Api: App\Api\*Presenter
In base a questa configurazione, il presentatore Front:Home
si riferisce alla classe
App\UI\Front\Home\HomePresenter
, mentre il presentatore Api:OAuth
si riferisce alla classe
App\Api\OAuthPresenter
.
Poiché i moduli Front
e Admin
hanno un approccio di mappatura simile e probabilmente ci saranno
altri moduli di questo tipo, è possibile creare una regola generale che li sostituisca. Un nuovo asterisco per il modulo viene
aggiunto alla maschera della classe:
application:
mapping:
*: App\UI\*\**Presenter
Api: App\Api\*Presenter
Per i moduli annidati a più livelli, come il presentatore Admin:User:Edit
, il segmento dell'asterisco si ripete
per ogni livello, dando luogo alla classe App\UI\Admin\User\Edit\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\UI, *, **Presenter]
Api: [App\Api, '', *Presenter]
Se abbiamo una sola regola nella configurazione, quella generale, possiamo scrivere brevemente:
application:
mapping: App\UI\*\**Presenter