Nette Documentation Preview

syntax
Módulos
*******

.[perex]
Os módulos dão clareza aos aplicativos Nette, facilitando a divisão em unidades lógicas.

Da mesma forma que organizamos os arquivos em pastas em um disco rígido, na Nette podemos dividir apresentadores, modelos e outras classes auxiliares em módulos. Como isso funciona na prática? Simplesmente incorporando novos subdiretórios à estrutura. Aqui está um exemplo de uma estrutura com dois módulos, Front e 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
│   │   └── ...
\--

Essa estrutura de diretórios é refletida nos namespaces das classes, portanto, por exemplo, `DashboardPresenter` está localizado no namespace `App\UI\Admin\Dashboard`:

```php
namespace App\UI\Admin\Dashboard;

class DashboardPresenter extends Nette\Application\UI\Presenter
{
	// ...
}
```

No aplicativo, nos referimos ao apresentador `Dashboard` dentro do módulo `Admin` usando a notação de dois pontos como `Admin:Dashboard`. Para sua ação `default`, nos referimos a ela como `Admin:Dashboard:default`.

A estrutura apresentada não é rígida; você pode [personalizá-la totalmente de acordo com suas necessidades |#mapping] na configuração. .[tip]

Os módulos podem incluir todos os outros arquivos, como componentes e classes auxiliares, além de apresentadores e modelos. Se estiver pensando em onde colocá-los, considere o uso de uma pasta `Accessory`:

/--pre
app/
├── UI/
│   ├── Admin/
│   │   ├── <b>Accessory/</b>
│   │   │   ├── FormFactory.php
│   │   │   └── AdminLayout.php
│   │   ├── Dashboard/
│   │   └── ...
\--


Módulos aninhados .[#toc-nested-modules]
----------------------------------------

Os módulos podem ter vários níveis de aninhamento, semelhante a uma estrutura de diretórios em um disco:

/--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
│   │   └── ...
\--

O módulo `Blog` é dividido em submódulos `Admin` e `Front`. Isso também se reflete nos namespaces, que aparecem como `App\UI\Blog\Admin` e similares. Para nos referirmos ao apresentador `Dashboard` dentro do submódulo `Admin`, nos referimos a ele como `Blog:Admin:Dashboard`.

O aninhamento pode ser tão profundo quanto necessário, permitindo a criação de sub-submódulos.

Por exemplo, se na administração você tem muitos apresentadores relacionados ao gerenciamento de pedidos, como `OrderDetail`, `OrderEdit`, `OrderDispatch`, etc., você pode criar um módulo `Order` no qual apresentadores como `Detail`, `Edit`, `Dispatch` e outros serão organizados.


Criação de links .[#toc-creating-links]
---------------------------------------

Os links nos modelos de apresentadores são relativos ao módulo atual. Assim, o link `Foo:default` leva ao apresentador `Foo` no mesmo módulo que o apresentador atual. Se o módulo atual é `Front`, por exemplo, então o link vai assim:

```latte
<a n:href="Product:show">link to Front:Product:show</a>
```

Um link é relativo mesmo que inclua o nome de um módulo, que é então considerado um submódulo:

```latte
<a n:href="Shop:Product:show">link to Front:Shop:Product:show</a>
```

Links absolutos são escritos analogamente a caminhos absolutos em disco, mas com colons ao invés de cortes. Assim, uma ligação absoluta começa com dois-pontos:

```latte
<a n:href=":Admin:Product:show">link to Admin:Product:show</a>
```

Para saber se estamos em um determinado módulo ou em seu submódulo, podemos usar a função `isModuleCurrent(moduleName)`.

```latte
<li n:class="isModuleCurrent('MyEshop:Users') ? active">
	<a n:href="Product:">...</a>
</li>
```


Roteiro .[#toc-routing]
-----------------------

Ver [capítulo sobre roteamento |routing#Modules].


Mapeamento .[#toc-mapping]
--------------------------

O mapeamento define as regras para derivar o nome da classe do nome do apresentador. Essas regras são especificadas na [configuração |configuration] sob a chave `application › mapping`.

As estruturas de diretório mencionadas anteriormente nesta página são baseadas no seguinte mapeamento:

```neon
application:
	mapping: App\UI\*\**Presenter
```

Como funciona o mapeamento? Para entender melhor, vamos primeiro imaginar um aplicativo sem módulos. Queremos que as classes do apresentador se enquadrem no namespace `App\UI`, de modo que o apresentador `Home` mapeie para a classe `App\UI\HomePresenter`. Isso pode ser obtido com esta configuração:

```neon
application:
	mapping: App\UI\*Presenter
```

Esse mapeamento funciona substituindo o asterisco na máscara `App\UI\*Presenter` pelo nome do apresentador `Home`, resultando no nome final da classe `App\UI\HomePresenter`. Simples!

Entretanto, como você pode ver nos exemplos deste e de outros capítulos, colocamos as classes de apresentador em subdiretórios homônimos, por exemplo, o apresentador `Home` é mapeado para a classe `App\UI\Home\HomePresenter`. Isso é feito duplicando-se o asterisco (requer o Nette Application 3.2):

```neon
application:
	mapping: App\UI\**Presenter
```

Agora, vamos passar a mapear os apresentadores em módulos. Podemos definir mapeamentos específicos para cada módulo:

```neon
application:
	mapping:
		Front: App\UI\Front\**Presenter
		Admin: App\UI\Admin\**Presenter
		Api: App\Api\*Presenter
```

De acordo com essa configuração, o apresentador `Front:Home` mapeia para a classe `App\UI\Front\Home\HomePresenter`, enquanto o apresentador `Api:OAuth` mapeia para a classe `App\Api\OAuthPresenter`.

Como os módulos `Front` e `Admin` têm uma abordagem de mapeamento semelhante e é provável que haja mais módulos desse tipo, é possível criar uma regra geral que os substitua. Um novo asterisco para o módulo é adicionado à máscara de classe:

```neon
application:
	mapping:
		*: App\UI\*\**Presenter
		Api: App\Api\*Presenter
```

Para módulos aninhados em vários níveis, como o apresentador `Admin:User:Edit`, o segmento de asterisco se repete para cada nível, resultando na classe `App\UI\Admin\User\Edit\EditPresenter`.

Uma notação alternativa é usar uma matriz composta de três segmentos em vez de uma cadeia de caracteres. Essa notação é equivalente à anterior:

```neon
application:
	mapping:
		*: [App\UI, *, **Presenter]
		Api: [App\Api, '', *Presenter]
```

Se tivermos apenas uma regra na configuração, a geral, podemos escrever de forma resumida:

```neon
application:
	mapping: App\UI\*\**Presenter
```

Módulos

Os módulos dão clareza aos aplicativos Nette, facilitando a divisão em unidades lógicas.

Da mesma forma que organizamos os arquivos em pastas em um disco rígido, na Nette podemos dividir apresentadores, modelos e outras classes auxiliares em módulos. Como isso funciona na prática? Simplesmente incorporando novos subdiretórios à estrutura. Aqui está um exemplo de uma estrutura com dois módulos, Front e Admin:

app/
├── UI/
│   ├── Admin/            ← Admin module
│   │   ├── @layout.latte
│   │   ├── Dashboard/
│   │   │   ├── DashboardPresenter.php
│   │   │   └── default.latte
│   │   └── ...
│   ├── Front/            ← Front module
│   │   ├── @layout.latte
│   │   ├── Home/
│   │   │   ├── HomePresenter.php
│   │   │   └── default.latte
│   │   └── ...

Essa estrutura de diretórios é refletida nos namespaces das classes, portanto, por exemplo, DashboardPresenter está localizado no namespace App\UI\Admin\Dashboard:

namespace App\UI\Admin\Dashboard;

class DashboardPresenter extends Nette\Application\UI\Presenter
{
	// ...
}

No aplicativo, nos referimos ao apresentador Dashboard dentro do módulo Admin usando a notação de dois pontos como Admin:Dashboard. Para sua ação default, nos referimos a ela como Admin:Dashboard:default.

A estrutura apresentada não é rígida; você pode personalizá-la totalmente de acordo com suas necessidades na configuração.

Os módulos podem incluir todos os outros arquivos, como componentes e classes auxiliares, além de apresentadores e modelos. Se estiver pensando em onde colocá-los, considere o uso de uma pasta Accessory:

app/
├── UI/
│   ├── Admin/
│   │   ├── Accessory/
│   │   │   ├── FormFactory.php
│   │   │   └── AdminLayout.php
│   │   ├── Dashboard/
│   │   └── ...

Módulos aninhados

Os módulos podem ter vários níveis de aninhamento, semelhante a uma estrutura de diretórios em um disco:

app/
├── UI/
│   ├── Blog/             ← Blog module
│   │   ├── Admin/        ← Admin submodule
│   │   │   ├── Dashboard/
│   │   │   └── ...
│   │   ├── Front/        ← Front submodule
│   │   │   ├── @layout.latte
│   │   │   ├── Home/
│   │   │   └── ...
│   ├── Forum/            ← Forum module
│   │   └── ...

O módulo Blog é dividido em submódulos Admin e Front. Isso também se reflete nos namespaces, que aparecem como App\UI\Blog\Admin e similares. Para nos referirmos ao apresentador Dashboard dentro do submódulo Admin, nos referimos a ele como Blog:Admin:Dashboard.

O aninhamento pode ser tão profundo quanto necessário, permitindo a criação de sub-submódulos.

Por exemplo, se na administração você tem muitos apresentadores relacionados ao gerenciamento de pedidos, como OrderDetail, OrderEdit, OrderDispatch, etc., você pode criar um módulo Order no qual apresentadores como Detail, Edit, Dispatch e outros serão organizados.

Os links nos modelos de apresentadores são relativos ao módulo atual. Assim, o link Foo:default leva ao apresentador Foo no mesmo módulo que o apresentador atual. Se o módulo atual é Front, por exemplo, então o link vai assim:

<a n:href="Product:show">link to Front:Product:show</a>

Um link é relativo mesmo que inclua o nome de um módulo, que é então considerado um submódulo:

<a n:href="Shop:Product:show">link to Front:Shop:Product:show</a>

Links absolutos são escritos analogamente a caminhos absolutos em disco, mas com colons ao invés de cortes. Assim, uma ligação absoluta começa com dois-pontos:

<a n:href=":Admin:Product:show">link to Admin:Product:show</a>

Para saber se estamos em um determinado módulo ou em seu submódulo, podemos usar a função isModuleCurrent(moduleName).

<li n:class="isModuleCurrent('MyEshop:Users') ? active">
	<a n:href="Product:">...</a>
</li>

Roteiro

Ver capítulo sobre roteamento.

Mapeamento

O mapeamento define as regras para derivar o nome da classe do nome do apresentador. Essas regras são especificadas na configuração sob a chave application › mapping.

As estruturas de diretório mencionadas anteriormente nesta página são baseadas no seguinte mapeamento:

application:
	mapping: App\UI\*\**Presenter

Como funciona o mapeamento? Para entender melhor, vamos primeiro imaginar um aplicativo sem módulos. Queremos que as classes do apresentador se enquadrem no namespace App\UI, de modo que o apresentador Home mapeie para a classe App\UI\HomePresenter. Isso pode ser obtido com esta configuração:

application:
	mapping: App\UI\*Presenter

Esse mapeamento funciona substituindo o asterisco na máscara App\UI\*Presenter pelo nome do apresentador Home, resultando no nome final da classe App\UI\HomePresenter. Simples!

Entretanto, como você pode ver nos exemplos deste e de outros capítulos, colocamos as classes de apresentador em subdiretórios homônimos, por exemplo, o apresentador Home é mapeado para a classe App\UI\Home\HomePresenter. Isso é feito duplicando-se o asterisco (requer o Nette Application 3.2):

application:
	mapping: App\UI\**Presenter

Agora, vamos passar a mapear os apresentadores em módulos. Podemos definir mapeamentos específicos para cada módulo:

application:
	mapping:
		Front: App\UI\Front\**Presenter
		Admin: App\UI\Admin\**Presenter
		Api: App\Api\*Presenter

De acordo com essa configuração, o apresentador Front:Home mapeia para a classe App\UI\Front\Home\HomePresenter, enquanto o apresentador Api:OAuth mapeia para a classe App\Api\OAuthPresenter.

Como os módulos Front e Admin têm uma abordagem de mapeamento semelhante e é provável que haja mais módulos desse tipo, é possível criar uma regra geral que os substitua. Um novo asterisco para o módulo é adicionado à máscara de classe:

application:
	mapping:
		*: App\UI\*\**Presenter
		Api: App\Api\*Presenter

Para módulos aninhados em vários níveis, como o apresentador Admin:User:Edit, o segmento de asterisco se repete para cada nível, resultando na classe App\UI\Admin\User\Edit\EditPresenter.

Uma notação alternativa é usar uma matriz composta de três segmentos em vez de uma cadeia de caracteres. Essa notação é equivalente à anterior:

application:
	mapping:
		*: [App\UI, *, **Presenter]
		Api: [App\Api, '', *Presenter]

Se tivermos apenas uma regra na configuração, a geral, podemos escrever de forma resumida:

application:
	mapping: App\UI\*\**Presenter