Moduly

Moduly vnášejí do Nette aplikací přehlednost díky snadnému členění do logických celků.

Podobně jako na pevném disku organizujeme soubory do jednotlivých složek, tak i v Nette můžeme presentery, šablony a další pomocné třídy rozdělovat do modulů. Jak to funguje v praxi? Jednoduše začleníme do struktury nové podadresáře. Příklad takové struktury se dvěma moduly Front a Admin:

app/
├── UI/
│   ├── Admin/            ← modul Admin
│   │   ├── @layout.latte
│   │   ├── Dashboard/
│   │   │   ├── DashboardPresenter.php
│   │   │   └── default.latte
│   │   └── ...
│   ├── Front/            ← modul Front
│   │   ├── @layout.latte
│   │   ├── Home/
│   │   │   ├── HomePresenter.php
│   │   │   └── default.latte
│   │   └── ...

Tato adresářová struktura se odráží ve jmenných prostorech tříd, takže například DashboardPresenter se nachází ve jmenném prostoru App\UI\Admin\Dashboard:

namespace App\UI\Admin\Dashboard;

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

Na presenter Dashboard uvnitř modulu Admin odkazujeme v aplikaci pomocí dvojtečkové notace jako na Admin:Dashboard. Na jeho akci default potom jako na Admin:Dashboard:default.

Představená struktura není pevná; můžete si ji zcela přizpůsobit dle svých potřeb v konfiguraci.

Moduly mohou kromě presenterů a šablon samozřejmě zahrnovat všechny ostatní soubory, jako jsou například komponenty a pomocné třídy. Pokud uvažujete, kam je zařadit, zvažte využití složky Accessory:

app/
├── UI/
│   ├── Admin/
│   │   ├── Accessory/
│   │   │   ├── FormFactory.php
│   │   │   └── AdminLayout.php
│   │   ├── Dashboard/
│   │   └── ...

Vnořené moduly

Moduly mohou mít více úrovní zanoření, podobně jako adresářová struktura na disku:

app/
├── UI/
│   ├── Blog/             ← modul Blog
│   │   ├── Admin/        ← submodul Admin
│   │   │   ├── Dashboard/
│   │   │   └── ...
│   │   ├── Front/        ← submodul Front
│   │   │   ├── @layout.latte
│   │   │   ├── Home/
│   │   │   └── ...
│   ├── Forum/            ← modul Forum
│   │   └── ...

Modul Blog je rozdělen na submoduly Admin a Front. To se projeví i ve jmenných prostorech, které pak budou vypadat jako App\UI\Blog\Admin a podobně. Na presenter Dashboard v rámci submodulu odkazujeme jako na Blog:Admin:Dashboard.

Zanoření může být libovolně hluboké, což umožňuje vytvářet sub-submoduly.

Pokud například v administraci máte mnoho presenterů týkajících se správy objednávek, jako jsou OrderDetail, OrderEdit, OrderDispatch atd., můžete pro lepší organizovanost vytvořit modul Order, ve kterém budou presentery Detail, Edit, Dispatch a další.

Vytváření odkazů

Odkazy v šablonách presenterů jsou relativní vůči aktuálnímu modulu. Tedy odkaz Foo:default vede na presenter Foo v tomtéž modulu, v jakém je aktuální presenter. Pokud je aktuální modul například Front, pak odkaz vede takto:

<a n:href="Product:show">odkaz na Front:Product:show</a>

Odkaz je relativní i pokud je jeho součástí název modulu, ten se pak považuje za submodul:

<a n:href="Shop:Product:show">odkaz na Front:Shop:Product:show</a>

Absolutní odkazy zapisujeme analogicky k absolutním cestám na disku, jen místo lomítek jsou dvojtečky. Tedy absolutní odkaz začíná dvojtečkou:

<a n:href=":Admin:Product:show">odkaz na Admin:Product:show</a>

Pro zjištění, zda jsme v určitém modulu nebo jeho submodulu, použijeme funkci isModuleCurrent(moduleName).

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

Routování

Viz kapitola o routování.

Mapování

Mapování definuje pravidla pro odvozování názvu třídy z názvu presenteru. Specifikujeme je v konfiguraci pod klíčem application › mapping.

Adresářové struktury uváděné výše na této stránce vycházejí z tohoto mapování:

application:
	mapping: App\UI\*\**Presenter

Jak mapování funguje? Pro lepší pochopení si nejprve představme aplikaci bez modulů. Chceme, aby třídy presenterů spadaly do jmenného prostoru App\UI, aby se presenter Home mapoval na třídu App\UI\HomePresenter. Což dosáhneme touto konfigurací:

application:
	mapping: App\UI\*Presenter

Mapování funguje tak, že název presenteru Home nahradí hvězdičku v masce App\UI\*Presenter, čímž získáme výsledný název třídy App\UI\HomePresenter. Jednoduché!

Jak ale vidíte v ukázkách v této a dalších kapitolách, třídy presenterů umisťujeme do eponymních podadresářů, například presenter Home se mapuje na třídu App\UI\Home\HomePresenter. Toho dosáhneme zdvojením dvojtečky (vyžaduje Nette Application 3.2):

application:
	mapping: App\UI\**Presenter

Nyní přistoupíme k mapování presenterů do modulů. Pro každý modul můžeme definovat specifické mapování:

application:
	mapping:
		Front: App\UI\Front\**Presenter
		Admin: App\UI\Admin\**Presenter
		Api: App\Api\*Presenter

Podle této konfigurace se presenter Front:Home mapuje na třídu App\UI\Front\Home\HomePresenter, zatímco presenter Api:OAuth na třídu App\Api\OAuthPresenter.

Protože moduly Front i Admin mají podobný způsob mapování a takových modulů bude nejspíš více, je možné vytvořit obecné pravidlo, které je nahradí. Do masky třídy tak přibude nová hvězdička pro modul:

application:
	mapping:
		*: App\UI\*\**Presenter
		Api: App\Api\*Presenter

Pro vícenásobně zanořené moduly, jako je například presenter Admin:User:Edit, se segment s hvězdičkou opakuje pro každou úroveň a výsledkem je třída App\UI\Admin\User\Edit\EditPresenter.

Alternativním zápisem je místo řetězce použít pole skládající se ze tří segmentů. Tento zápis je ekvivaletní s předchozím:

application:
	mapping:
		*: [App\UI, *, **Presenter]
		Api: [App\Api, '', *Presenter]

Pokud bychom měli v konfiguraci jen jediné pravidlo, ono obecné, můžeme zkráceně zapsat:

application:
	mapping: App\UI\*\**Presenter