Nette Documentation Preview

syntax
Moduly
******

.[perex]
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:

/--pre
app/
├── UI/
│   ├── <b>Admin/</b>            ← modul Admin
│   │   ├── @layout.latte
│   │   ├── Dashboard/
│   │   │   ├── DashboardPresenter.php
│   │   │   └── default.latte
│   │   └── ...
│   ├── <b>Front/</b>            ← 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`:

```php
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|#mapování] v konfiguraci. .[tip]

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`:

/--pre
app/
├── UI/
│   ├── Admin/
│   │   ├── <b>Accessory/</b>
│   │   │   ├── FormFactory.php
│   │   │   └── AdminLayout.php
│   │   ├── Dashboard/
│   │   └── ...
\--


Vnořené moduly
--------------

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

/--pre
app/
├── UI/
│   ├── <b>Blog/</b>             ← modul Blog
│   │   ├── <b>Admin/</b>        ← submodul Admin
│   │   │   ├── Dashboard/
│   │   │   └── ...
│   │   ├── <b>Front/</b>        ← submodul Front
│   │   │   ├── @layout.latte
│   │   │   ├── Home/
│   │   │   └── ...
│   ├── <b>Forum/</b>            ← 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:

```latte
<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:

```latte
<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:

```latte
<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)`.

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


Routování
---------

Viz [kapitola o routování |routing#Moduly].


Mapování
--------

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

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

```neon
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í:

```neon
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):

```neon
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í:

```neon
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:

```neon
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:

```neon
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:

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

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