Модули
В 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
.