Модулі
У Nette модулі являють собою логічні одиниці, з яких складається додаток. Вони включають ведучі, шаблони, можливо, компоненти та класи моделей.
Одного компонента для презентаторів і одного для шаблонів буде недостатньо для реальних проектів. Наявність десятків файлів в одній папці щонайменше неорганізована. Як вийти з цього становища? Ми просто розділяємо їх на підкаталоги на диску і на простори імен у коді. І це саме те, що роблять модулі Nette.
Тому давайте забудемо про єдину папку для ведучих і шаблонів і
натомість створимо модулі, наприклад, Admin
і Front
.
app/ ├──Presenters/├── Modules/ ← директория с модулями │ ├── Admin/ ← модуль Admin │ │ ├── Presenters/ ← его презентеры │ │ │ ├── DashboardPresenter.php │ │ │ └── templates/ │ └── Front/ ← модуль Front │ └── Presenters/ ← его презентеры │ └── ...
Ця структура каталогів буде відображена в просторах імен класів, так,
наприклад, DashboardPresenter
буде знаходитися в просторі
App\Modules\Admin\Presenters
:
namespace App\Modules\Admin\Presenters;
class DashboardPresenter extends Nette\Application\UI\Presenter
{
// ...
}
Ведучий Dashboard
усередині модуля Admin
позначається в
додатку за допомогою подвійної точкової нотації як Admin:Dashboard
, а
його дія default
позначається як Admin:Dashboard:default
. А звідки Nette
знає, що Admin:Dashboard
представляє клас
App\Modules\Admin\Presenters\DashboardPresenter
? Ми говоримо про це, використовуючи відображення в конфігурації. Таким чином, наведена
структура не є фіксованою, і ви можете змінювати її на свій розсуд.
Модулі, звісно, можуть містити всі інші частини, крім презентаторів і шаблонів, такі як компоненти, класи моделей тощо.
Вкладені модулі
Модулі не обов'язково повинні формувати тільки плоску структуру, ви також можете створювати, наприклад, підмодулі:
app/ ├── Modules/ ← директория с модулями │ ├── Blog/ ← модуль Blog │ │ ├── Admin/ ← подмодуль Admin │ │ │ ├── Presenters/ │ │ │ └── ... │ │ └── Front/ ← подмодуль Front │ │ ├── Presenters/ │ │ └── ... │ ├── Forum/ ← модуль Forum │ │ └── ...
Таким чином, модуль Blog
розбивається на підмодулі Admin
і
Front
. І знову ж таки це буде відображено в просторах імен, які
будуть App\Modules\Blog\Admin\Presenters
тощо. Ведучий Dashboard
всередині
підмодуля називається Blog:Admin:Dashboard
.
Розгалуження може бути настільки глибоким, наскільки ви захочете, тому ви можете створювати підмодулі.
Створення посилань
Посилання в шаблонах ведучого є відносними щодо поточного модуля.
Таким чином, посилання 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
.
Почнемо з прикладу, в якому не використовуються модулі. Ми просто
хочемо, щоб класи ведучого мали простір імен App\Presenters
. Тобто ми
хочемо, щоб ведучий, наприклад, Home
відображався на клас
App\Presenters\HomePresenter
. Цього можна досягти за допомогою такої
конфігурації:
application:
mapping:
*: App\Presenters\*Presenter
Ім'я презентера замінюється зірочкою, і в результаті виходить назва класу. Легко!
Якщо ми розділимо доповідачів на модулі, то для кожного модуля в нас може бути свій маппінг:
application:
mapping:
Front: App\Modules\Front\Presenters\*Presenter
Admin: App\Modules\Admin\Presenters\*Presenter
Api: App\Api\*Presenter
Тепер презентер Front:Home
визначається класом
App\Modules\Front\HomePresenter
, а презентер Admin:Dashboard
` –
App\AdminModule\DashboardPresenter
.
Зручніше буде створити загальне правило (зірочка), яке замінить перші два правила і додасть додаткову зірочку тільки для модуля:
application:
mapping:
*: App\Modules\*\Presenters\*Presenter
Api: App\Api\*Presenter
Але що якщо ми використовуємо кілька вкладених модулів і в нас є,
наприклад, провідний Admin:User:Edit
? У цьому випадку сегмент із
зірочкою, що представляє модуль для кожного рівня, буде просто
повторюватися, і результатом буде клас
App\Modules\Admin\User\Presenters\EditPresenter
.
Альтернативною нотацією є використання масиву, що складається з трьох сегментів, замість рядка. Ця нотація еквівалентна попередній:
application:
mapping:
*: [App\Modules, *, Presenters\*Presenter]
Значення за замовчуванням – *: *Module\*Presenter
.