Модулі

Модулі вносять ясність у додатки 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
версію: 4.0