Módulos

Los módulos aportan claridad a las aplicaciones Nette al facilitar su división en unidades lógicas.

De forma similar a la organización de archivos en carpetas en un disco duro, en Nette podemos dividir los presentadores, plantillas y otras clases auxiliares en módulos. ¿Cómo funciona esto en la práctica? Simplemente incorporando nuevos subdirectorios a la estructura. He aquí un ejemplo de estructura con dos módulos, Front y Admin:

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

Esta estructura de directorios se refleja en los espacios de nombres de las clases, así por ejemplo, DashboardPresenter se encuentra en el espacio de nombres App\UI\Admin\Dashboard:

namespace App\UI\Admin\Dashboard;

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

En la aplicación, nos referimos al presentador Dashboard dentro del módulo Admin utilizando la notación de dos puntos como Admin:Dashboard. Para su acción default, nos referimos a él como Admin:Dashboard:default.

La estructura presentada no es rígida; puede adaptarla totalmente a sus necesidades en la configuración.

Los módulos pueden incluir todos los demás archivos, como componentes y clases auxiliares, además de presentadores y plantillas. Si está pensando dónde colocarlos, considere la posibilidad de utilizar una carpeta Accessory:

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

Módulos anidados

Los módulos pueden tener múltiples niveles de anidamiento, similar a una estructura de directorios en un disco:

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

El módulo Blog se divide en los submódulos Admin y Front. Esto también se refleja en los espacios de nombres, que aparecen como App\UI\Blog\Admin y similares. Para referirnos al presentador Dashboard dentro del submódulo Admin, lo denominamos Blog:Admin:Dashboard.

El anidamiento puede ser tan profundo como sea necesario, permitiendo la creación de sub-submódulos.

Por ejemplo, si en administración tiene muchos presentadores relacionados con la gestión de pedidos, como OrderDetail, OrderEdit, OrderDispatch, etc., puede crear un módulo Order en el que se organizarán presentadores como Detail, Edit, Dispatch, y otros.

Los enlaces de las plantillas de presentador son relativos al módulo actual. Así, el enlace Foo:default lleva al presentador Foo en el mismo módulo que el presentador actual. Si el módulo actual es Front, por ejemplo, el enlace será el siguiente:

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

Un enlace es relativo aunque incluya el nombre de un módulo, que se considera entonces un submódulo:

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

Los enlaces absolutos se escriben de forma análoga a las rutas absolutas en disco, pero con dos puntos en lugar de barras. Así, un enlace absoluto comienza con dos puntos:

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

Para saber si estamos en un módulo determinado o en su submódulo podemos utilizar la función isModuleCurrent(moduleName).

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

Enrutamiento

Véase el capítulo sobre en rutamiento.

Cartografía

El mapeo define las reglas para derivar el nombre de la clase del nombre del presentador. Estas reglas se especifican en la configuración bajo la clave application › mapping.

Las estructuras de directorios mencionadas anteriormente en esta página se basan en la siguiente asignación:

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

¿Cómo funciona el mapeo? Para entenderlo mejor, imaginemos primero una aplicación sin módulos. Queremos que las clases del presentador pertenezcan al espacio de nombres App\UI, de modo que el presentador Home se asigne a la clase App\UI\HomePresenter. Esto se puede lograr con esta configuración:

application:
	mapping: App\UI\*Presenter

Este mapeo funciona reemplazando el asterisco en la máscara App\UI\*Presenter con el nombre del presentador Home, resultando en el nombre final de la clase App\UI\HomePresenter. Es muy sencillo.

Sin embargo, como puede ver en los ejemplos de este y otros capítulos, colocamos las clases de presentador en subdirectorios epónimos, por ejemplo, el presentador Home se asigna a la clase App\UI\Home\HomePresenter. Esto se consigue duplicando el asterisco (requiere Nette Application 3.2):

application:
	mapping: App\UI\**Presenter

Pasemos ahora a la asignación de presentadores a módulos. Podemos definir asignaciones específicas para cada módulo:

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

Según esta configuración, el presentador Front:Home se asigna a la clase App\UI\Front\Home\HomePresenter, mientras que el presentador Api:OAuth se asigna a la clase App\Api\OAuthPresenter.

Puesto que los módulos Front y Admin tienen un enfoque de asignación similar y es probable que haya más módulos de este tipo, es posible crear una regla general que los sustituya. Se añade un nuevo asterisco para el módulo a la máscara de la clase:

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

Para los módulos anidados de varios niveles, como el presentador Admin:User:Edit, el segmento del asterisco se repite para cada nivel, lo que da como resultado la clase App\UI\Admin\User\Edit\EditPresenter.

Una notación alternativa consiste en utilizar una matriz compuesta por tres segmentos en lugar de una cadena. Esta notación es equivalente a la anterior:

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

Si sólo tenemos una regla en la configuración, la general, podemos escribir brevemente:

application:
	mapping: App\UI\*\**Presenter
versión: 4.0