Модули
Модулите внасят яснота в приложенията на 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