Nette Documentation Preview

syntax
Модулі
******

.[perex]
Модулі вносять ясність у додатки Nette, полегшуючи поділ на логічні блоки.

Подібно до організації файлів у папки на жорсткому диску, в Nette ми можемо розділити презентатори, шаблони та інші допоміжні класи на модулі. Як це працює на практиці? Просто додаванням нових підкаталогів до структури. Ось приклад структури з двома модулями, Front і Admin:

/--pre
app/
├── UI/
│   ├── <b>Admin/</b>            ← Admin module
│   │   ├── @layout.latte
│   │   ├── Dashboard/
│   │   │   ├── DashboardPresenter.php
│   │   │   └── default.latte
│   │   └── ...
│   ├── <b>Front/</b>            ← Front module
│   │   ├── @layout.latte
│   │   ├── Home/
│   │   │   ├── HomePresenter.php
│   │   │   └── default.latte
│   │   └── ...
\--

Ця структура каталогів відображається в просторах імен класів, тому, наприклад, `DashboardPresenter` знаходиться в просторі імен `App\UI\Admin\Dashboard`:

```php
namespace App\UI\Admin\Dashboard;

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

У програмі ми звертаємось до доповідача `Dashboard` у модулі `Admin`, використовуючи двокрапку, як `Admin:Dashboard`. Для його дії `default` ми звертаємось до нього як `Admin:Dashboard:default`.

Представлена структура не є жорсткою; ви можете [повністю налаштувати її відповідно до ваших потреб |#mapping] у конфігурації. .[tip]

Модулі можуть включати всі інші файли, такі як компоненти і допоміжні класи, на додаток до презентаторів і шаблонів. Якщо ви обмірковуєте, де їх розмістити, розгляньте можливість використання папки `Accessory`:

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


Вкладені модулі .[#toc-nested-modules]
--------------------------------------

Модулі можуть мати кілька рівнів вкладеності, подібно до структури каталогів на диску:

/--pre
app/
├── UI/
│   ├── <b>Blog/</b>             ← Blog module
│   │   ├── <b>Admin/</b>        ← Admin submodule
│   │   │   ├── Dashboard/
│   │   │   └── ...
│   │   ├── <b>Front/</b>        ← Front submodule
│   │   │   ├── @layout.latte
│   │   │   ├── Home/
│   │   │   └── ...
│   ├── <b>Forum/</b>            ← Forum module
│   │   └── ...
\--

Модуль `Blog` поділяється на підмодулі `Admin` і `Front`. Це також відображається у просторах імен, які потім з'являються як `App\UI\Blog\Admin` і подібним чином. Щоб звернутися до доповідача `Dashboard` у підмодулі `Admin`, ми посилаємося на нього як `Blog:Admin:Dashboard`.

Вкладеність може бути настільки глибокою, наскільки це необхідно, що дозволяє створювати підмодулі.

Наприклад, якщо в адмініструванні ви маєте багато доповідачів, пов'язаних з управлінням замовленнями, таких як `OrderDetail`, `OrderEdit`, `OrderDispatch` і т.д., ви можете створити модуль `Order`, в якому будуть організовані доповідачі `Detail`, `Edit`, `Dispatch` та інші.


Створення посилань .[#toc-creating-links]
-----------------------------------------

Посилання в шаблонах ведучого є відносними щодо поточного модуля. Таким чином, посилання `Foo:default` веде до ведучого `Foo` у тому ж модулі, що й поточний ведучий. Наприклад, якщо поточним модулем є `Front`, то посилання має такий вигляд:

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

Посилання є відносним, навіть якщо ім'я модуля є його частиною, тоді він вважається підмодулем:

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

Абсолютні посилання записуються аналогічно абсолютним шляхам на диску, але з двокрапками замість косих рисок. Таким чином, абсолютне посилання починається з двокрапки:

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

Щоб дізнатися, чи перебуваємо ми в певному модулі або підмодулі, ми використовуємо функцію `isModuleCurrent(moduleName)`.

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


Маршрутизація .[#toc-routing]
-----------------------------

Див. [розділ про маршрутизацію |routing#modules].


Картографування .[#toc-mapping]
-------------------------------

Відображення визначає правила отримання імені класу з імені доповідача. Ці правила задаються у [конфігурації |configuration] під ключем `application › mapping`.

Структури каталогів, згадані раніше на цій сторінці, базуються на наступному відображенні:

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

Як працює мапування? Для кращого розуміння, давайте спочатку уявимо додаток без модулів. Ми хочемо, щоб класи доповідача потрапляли до простору імен `App\UI`, щоб доповідач `Home` відображався у клас `App\UI\HomePresenter`. Цього можна досягти за допомогою такої конфігурації:

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

Це відображення працює шляхом заміни зірочки у масці `App\UI\*Presenter` на ім'я доповідача `Home`, в результаті чого ми отримаємо кінцеве ім'я класу `App\UI\HomePresenter`. Все просто!

Однак, як ви можете бачити у прикладах у цій та інших главах, ми розміщуємо класи доповідачів у однойменних підкаталогах, наприклад, доповідач `Home` зіставляється з класом `App\UI\Home\HomePresenter`. Це досягається за допомогою подвоєння зірочки (потрібно Nette Application 3.2):

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

Тепер перейдемо до зіставлення доповідачів з модулями. Для кожного модуля ми можемо визначити специфічні відображення:

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

Згідно з цією конфігурацією, доповідач `Front:Home` зіставляється з класом `App\UI\Front\Home\HomePresenter`, а доповідач `Api:OAuth` зіставляється з класом `App\Api\OAuthPresenter`.

Оскільки модулі `Front` і `Admin` мають подібний підхід до зіставлення і таких модулів, ймовірно, буде більше, можна створити загальне правило, яке замінить їх. До маски класу буде додано нову зірочку для модуля:

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

Для багаторівневих вкладених модулів, таких як доповідач `Admin:User:Edit`, сегмент зірочки повторюється для кожного рівня, в результаті чого утворюється клас `App\UI\Admin\User\Edit\EditPresenter`.

Альтернативним варіантом запису є використання масиву, що складається з трьох сегментів, замість рядка. Цей запис еквівалентний попередньому:

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

Якщо в конфігурації є лише одне правило, загальне, ми можемо написати його коротко:

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

Модулі

Модулі вносять ясність у додатки Nette, полегшуючи поділ на логічні блоки.

Подібно до організації файлів у папки на жорсткому диску, в Nette ми можемо розділити презентатори, шаблони та інші допоміжні класи на модулі. Як це працює на практиці? Просто додаванням нових підкаталогів до структури. Ось приклад структури з двома модулями, Front і Admin:

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

Ця структура каталогів відображається в просторах імен класів, тому, наприклад, DashboardPresenter знаходиться в просторі імен App\UI\Admin\Dashboard:

namespace App\UI\Admin\Dashboard;

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

У програмі ми звертаємось до доповідача Dashboard у модулі Admin, використовуючи двокрапку, як Admin:Dashboard. Для його дії default ми звертаємось до нього як Admin:Dashboard:default.

Представлена структура не є жорсткою; ви можете повністю налаштувати її відповідно до ваших потреб у конфігурації.

Модулі можуть включати всі інші файли, такі як компоненти і допоміжні класи, на додаток до презентаторів і шаблонів. Якщо ви обмірковуєте, де їх розмістити, розгляньте можливість використання папки Accessory:

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

Вкладені модулі

Модулі можуть мати кілька рівнів вкладеності, подібно до структури каталогів на диску:

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

Модуль Blog поділяється на підмодулі Admin і Front. Це також відображається у просторах імен, які потім з'являються як App\UI\Blog\Admin і подібним чином. Щоб звернутися до доповідача Dashboard у підмодулі Admin, ми посилаємося на нього як Blog:Admin:Dashboard.

Вкладеність може бути настільки глибокою, наскільки це необхідно, що дозволяє створювати підмодулі.

Наприклад, якщо в адмініструванні ви маєте багато доповідачів, пов'язаних з управлінням замовленнями, таких як OrderDetail, OrderEdit, OrderDispatch і т.д., ви можете створити модуль Order, в якому будуть організовані доповідачі Detail, Edit, Dispatch та інші.

Посилання в шаблонах ведучого є відносними щодо поточного модуля. Таким чином, посилання Foo:default веде до ведучого Foo у тому ж модулі, що й поточний ведучий. Наприклад, якщо поточним модулем є Front, то посилання має такий вигляд:

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

Посилання є відносним, навіть якщо ім'я модуля є його частиною, тоді він вважається підмодулем:

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

Абсолютні посилання записуються аналогічно абсолютним шляхам на диску, але з двокрапками замість косих рисок. Таким чином, абсолютне посилання починається з двокрапки:

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

Щоб дізнатися, чи перебуваємо ми в певному модулі або підмодулі, ми використовуємо функцію isModuleCurrent(moduleName).

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

Маршрутизація

Див. розділ про маршрутизацію.

Картографування

Відображення визначає правила отримання імені класу з імені доповідача. Ці правила задаються у конфігурації під ключем application › mapping.

Структури каталогів, згадані раніше на цій сторінці, базуються на наступному відображенні:

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

Як працює мапування? Для кращого розуміння, давайте спочатку уявимо додаток без модулів. Ми хочемо, щоб класи доповідача потрапляли до простору імен App\UI, щоб доповідач Home відображався у клас App\UI\HomePresenter. Цього можна досягти за допомогою такої конфігурації:

application:
	mapping: App\UI\*Presenter

Це відображення працює шляхом заміни зірочки у масці App\UI\*Presenter на ім'я доповідача Home, в результаті чого ми отримаємо кінцеве ім'я класу App\UI\HomePresenter. Все просто!

Однак, як ви можете бачити у прикладах у цій та інших главах, ми розміщуємо класи доповідачів у однойменних підкаталогах, наприклад, доповідач Home зіставляється з класом App\UI\Home\HomePresenter. Це досягається за допомогою подвоєння зірочки (потрібно Nette Application 3.2):

application:
	mapping: App\UI\**Presenter

Тепер перейдемо до зіставлення доповідачів з модулями. Для кожного модуля ми можемо визначити специфічні відображення:

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

Згідно з цією конфігурацією, доповідач Front:Home зіставляється з класом App\UI\Front\Home\HomePresenter, а доповідач Api:OAuth зіставляється з класом App\Api\OAuthPresenter.

Оскільки модулі Front і Admin мають подібний підхід до зіставлення і таких модулів, ймовірно, буде більше, можна створити загальне правило, яке замінить їх. До маски класу буде додано нову зірочку для модуля:

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

Для багаторівневих вкладених модулів, таких як доповідач Admin:User:Edit, сегмент зірочки повторюється для кожного рівня, в результаті чого утворюється клас App\UI\Admin\User\Edit\EditPresenter.

Альтернативним варіантом запису є використання масиву, що складається з трьох сегментів, замість рядка. Цей запис еквівалентний попередньому:

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

Якщо в конфігурації є лише одне правило, загальне, ми можемо написати його коротко:

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