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]
---------------------------------

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>

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

См. главу о маршрутизации.

Составление карты

Mapping определяет правила получения имени класса из имени ведущего. Эти правила задаются в конфигурации под ключом 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