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.
Creación de enlaces
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