Modulok

A Nette-ben a modulok az alkalmazást alkotó logikai egységeket jelentik. Ide tartoznak a prezenterek, sablonok, esetleg komponensek és modellosztályok.

Egy könyvtár a bemutatóknak és egy a sablonoknak nem lenne elég a valódi projektekhez. Több tucat fájl egy mappában való elhelyezése legalábbis rendezetlen. Hogyan szabadulhatunk meg ettől? Egyszerűen felosztjuk őket alkönyvtárakra a lemezen és névterekre a kódban. És pontosan ezt teszik a Nette modulok.

Felejtsük el tehát az egyetlen mappát az előadóknak és a sablonoknak, és helyette hozzunk létre modulokat, például a Admin és a Front.

app/
├── Presenters/
├── Modules/              ← directory with modules
│   ├── Admin/            ← module Admin
│   │   ├── Presenters/   ← its presenters
│   │   │   ├── DashboardPresenter.php
│   │   │   └── templates/
│   └── Front/            ← module Front
│       └── Presenters/   ← its presenters
│           └── ...

Ezt a könyvtárszerkezetet az osztályok névterei is tükrözni fogják, így például a DashboardPresenter a App\Modules\Admin\Presenters névtérben lesz:

namespace App\Modules\Admin\Presenters;

class DashboardPresenter extends Nette\Application\UI\Presenter
{
	// ...
}

A Dashboard prezenterre a Admin modulon belül az alkalmazáson belül a kettőspont jelöléssel Admin:Dashboard, a default műveletre pedig Admin:Dashboard:default néven hivatkozunk. És honnan tudja a Nette proper, hogy a Admin:Dashboard a App\Modules\Admin\Presenters\DashboardPresenter osztályt képviseli? Ezt a konfigurációban történő leképezéssel határozzuk meg. A megadott struktúra tehát nem keményen meghatározott, és Ön az igényeinek megfelelően módosíthatja.

A modulok természetesen a prezentereken és sablonokon kívül minden más elemet is tartalmazhatnak, például komponenseket, modellosztályokat stb.

Beágyazott modulok

A moduloknak nem kell csak sima struktúrát alkotniuk, létrehozhatunk például almodulokat is:

app/
├── Modules/              ← directory with modules
│   ├── Blog/             ← module Blog
│   │   ├── Admin/        ← submodule Admin
│   │   │   ├── Presenters/
│   │   │   └── ...
│   │   └── Front/        ← submodule Front
│   │       ├── Presenters/
│   │       └── ...
│   ├── Forum/            ← module Forum
│   │   └── ...

Így a Blog modul Admin és Front almodulokra oszlik. Ez ismét tükröződik a névterekben, amelyek a App\Modules\Blog\Admin\Presenters stb. lesznek. Az almodulon belüli Dashboard bemutatót Blog:Admin:Dashboard néven említjük.

A beágyazás tetszőlegesen mélyre mehet, így al-almodulok hozhatók létre.

A bemutatósablonokban lévő hivatkozások az aktuális modulhoz viszonyítva vannak. Így a Foo:default hivatkozás a Foo bemutatóhoz vezet, amely ugyanabban a modulban található, mint az aktuális bemutató. Ha az aktuális modul például a Front, akkor a link így néz ki:

<a n:href="Product:show">link to Front:Product:show</a>

A hivatkozás akkor is relatív, ha egy modul nevét tartalmazza, amely ilyenkor almodulnak minősül:

<a n:href="Shop:Product:show">link to Front:Shop:Product:show</a>

Az abszolút hivatkozások a lemezen lévő abszolút elérési utakhoz hasonlóan íródnak, de a kettőspontok helyett kettőspontokkal. Az abszolút link tehát kettősponttal kezdődik:

<a n:href=":Admin:Product:show">link to Admin:Product:show</a>

Hogy megtudjuk, hogy egy adott modulban vagy annak almoduljában vagyunk-e, használhatjuk a isModuleCurrent(moduleName) függvényt.

<li n:class="isModuleCurrent('MyEshop:Users') ? active">
	<a n:href="Product:">...</a>
</li>

Útválasztás

Lásd az útválasztásról szóló fejezetet.

Feltérképezés

Meghatározza azokat a szabályokat, amelyek alapján az osztály neve az előadó nevéből származik. Ezeket a konfigurációban a application › mapping kulcs alatt írjuk le.

Kezdjük egy olyan példával, amely nem használ modulokat. Csak azt akarjuk, hogy a prezenter osztályok a App\Presenters névtérrel rendelkezzenek. Ez azt jelenti, hogy egy olyan prezenternek, mint a Home, a App\Presenters\HomePresenter osztályhoz kell kapcsolódnia. Ezt a következő konfigurációval érhetjük el:

application:
	mapping:
		*: App\Presenters\*Presenter

Az osztálymaszkban a prezenter nevét csillaggal helyettesítjük, és az eredmény az osztály neve lesz. Easy!

Ha az előadókat modulokra osztjuk, akkor minden modulhoz saját leképezésünk lehet:

application:
	mapping:
		Front: App\Modules\Front\Presenters\*Presenter
		Admin: App\Modules\Admin\Presenters\*Presenter
		Api: App\Api\*Presenter

Most a Front:Home bemutatót a App\Modules\Front\Presenters\HomePresenter osztályra, a Admin:Dashboard bemutatót pedig a App\Modules\Admin\Presenters\DashboardPresenter osztályra képezzük le.

Praktikusabb egy általános (csillag) szabályt létrehozni az első kettő helyett. Az extra csillagot csak a modul számára adjuk hozzá az osztálymaszkhoz:

application:
	mapping:
		*: App\Modules\*\Presenters\*Presenter
		Api: App\Api\*Presenter

De mi van akkor, ha egymásba ágyazott modulokat használunk, és van egy bemutató Admin:User:Edit? Ebben az esetben a modult jelképező csillaggal ellátott szegmens minden szinten egyszerűen megismétlődik, és az eredmény a App\Modules\Admin\User\Presenters\EditPresenter osztály lesz.

Egy alternatív jelölés az, hogy a karakterlánc helyett egy három szegmensből álló tömböt használunk. Ez a jelölés egyenértékű az előzővel:

application:
	mapping:
		*: [App\Modules, *, Presenters\*Presenter]

Az alapértelmezett érték a *: *Module\*Presenter.