Una de las necesidades más frecuentes cuando realizamos una web es incluir un área de administración, una zona privada para clientes, etc con una plantilla diferente de la que utilizamos en el área principal. En Zend Framework 2 es una operación bastante sencilla y he recopilado en un sólo post cómo realizar dicho cambio de layout a nivel de Módulo, Controlador y Acción.

Cambio de layout de un Módulo

La solución más sencilla la ofrece un desarrollo muy simple y además muy eficaz de Evan Coury. Como sabemos cada módulo en ZF2 ejecuta de forma independiente su popio bootstrapping, por lo que a la hora de ejecutar nuestro módulo podemos inyectar en el dispatch el layout que nos interese y se aplicará en cualquiera de los controladores de nuestro módulo.

Para facilitar la tarea el propio Evan Coury ha desarrollado un módulo que simplemente tras instalarlo en la carpeta /vendor de nuestra aplicación y activarlo en nuestro aplication.config.php nos facilita enormemente la tarea de implementarlo. Ahora simplemente tendremos que añadir un nuevo array en el módulo.config.php del módulo para especificar qué layout emplear.

Supongamos que tenemos un módulo Admin que en nuestra aplicación nos permite acceder a un área de administración web. Para cambiar el layout a emplear en este módulo y tras activar el módulo EdpModuleLayouts incluiremo el array array module_layouts con la información del layout. Por supuesto debemos de recordar declararlo en el template_map:

[...]
'view_manager' => array(
  'template_map' => array(
    'admin/layout' => __DIR__ . '/../view/layout/admin.phtml',
    'login/layout' => __DIR__ . '/../view/layout/login.phtml',
    'logout/layout' => __DIR__ . '/../view/layout/logout.phtml',
    'partial/navbar' => __DIR__ . '/../view/layout/partial/navbar.phtml',
  ),
  'template_path_stack' => array(
    'admin' => __DIR__ . '/../view',
  ),
),
'module_layouts' => array(
  'Admin' => 'admin/layout',
),
[...]

Cambio de layout de un Controlador

Para realizar esta operación, y si habéis revisado el código de Evan Coury, lo que podemos hacer es almacenar en un array el nombre del/los controladores que queremos modificar su layout y escribir un nuevo array controller_layouts en el fichero módulo.config.php. Para ello vamos a realizar una sencilla modificación del código original de EdpModuleLayouts que nos permita ampliar su funcionalidad.

<?php
 
namespace EdpModuleLayouts;
 
class Module {
 
public function onBootstrap($e)
{
$e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController', 'dispatch', function($e) {
 
$routeMatchParams = $e->getRouteMatch()->getParams();
 
// Avoid errors on redirections, forwards, etc
if (!isset($routeMatchParams['__NAMESPACE__']) ||!isset($routeMatchParams['controller']) ||!isset($routeMatchParams['action'])) {
return;
}
 
$moduleName = substr($routeMatchParams['__NAMESPACE__'], 0, strpos($routeMatchParams['__NAMESPACE__'], '\\'));
$controllerName = str_replace('\\Controller\\', '/', $routeMatchParams['controller']);      
$actionName = $routeMatchParams['action'];
 
$config = $e->getApplication()->getServiceManager()->get('config');
$controller = $e->getTarget();
 
if (isset($config['module_layouts'][$moduleName]))
{
$controller->layout($config['module_layouts'][$moduleName]);   
}
if (isset($config['controller_layouts'][$controllerName]))
{
$controller->layout($config['controller_layouts'][$controllerName]);
}
if (isset($config['action_layouts'][$controllerName . '/' . $actionName]))
{
$controller->layout($config['action_layouts'][$controllerName . '/' . $actionName]);
}      
 
}, 100);
}
}

Es importante destacar que cuando definamos el nombre del controlador en el array deberemos incluir la sintaxis Módulo/Controlador. Sino corremos el riesgo de modificar el layout en controladores con el mismo nombre pero en diferentes módulos.

Imaginemos que tenemos un controlador de login en nuestro área de administración que sólo cuenta con un formulario de validación y por lo tanto tiene un layout diferente. Incluiremos pues el array controller_layouts en el fichero módulo.config.php que quedará como sigue.

[...]
'view_manager' => array(
'template_map' => array(
'admin/layout' => __DIR__ . '/../view/layout/admin.phtml',
'login/layout' => __DIR__ . '/../view/layout/login.phtml',
'logout/layout' => __DIR__ . '/../view/layout/logout.phtml',
'partial/navbar' => __DIR__ . '/../view/layout/partial/navbar.phtml',
),
'template_path_stack' => array(
'admin' => __DIR__ . '/../view',
),
),
'module_layouts' => array(
'Admin' => 'admin/layout',
),
'controller_layouts' => array(
'Admin/Login' => 'login/layout',
),
[...]

Cambio de layout de un Action

Una de las operaciones más sencillas es cambiar el layout de un action. Podemos realizar dicha operación en el propio controlador. Pongamos como ejemplo que en nuestro controlador LoginController.php necesitamos un layout diferente para la acción de logout. Para ello simplemente podemos dejar así el controlador:

namespace Admin\Controller;
 
use Zend\Mvc\Controller\AbstractActionController;
use Zend\EventManager\EventManagerInterface;
 
class LoginController extends AbstractActionController {
 
public function indexAction()
{
[...]
}
 
public function logoutAction()
{
$this->layout('logout/layout');
[...]
}
 
}

Sin embargo no es muy elegante. Si te has fijado en el código del apartado anterior ya hemos modificado el módulo EdpModuleLayouts para que también soporte en el módulo.config.php definir el layout para un action, de modo que quedaría así:

'module_layouts' => array(
'Admin' => 'admin/layout',
),
'controller_layouts' => array(
'Admin/Login' => 'login/layout',
),
'action_layouts' => array(
'Admin/Login/logout' => 'logout/layout',
),
[...]

Conclusión

En definitiva como podemos ver la operación de cambiar el layout es muy sencilla, pero el uso de módulos y realizar dichos cambios en los ficheros de configuración nos permiten una escalabilidad y un mayor desacoplamiento de funcionalidad y configuración. Como siempre estos son los métodos que yo empleo, así que si alguien utiliza otros o quiere realizar un aporte o corrección encantado de recibir comentarios.

ACTUALIZACIÓN 17/07/2015: En el caso de realizar una redirección o un forward desde un action en el controlador el módulo arrojaba un error sino se le proporcionaba el módulo y controlador junto con el action. Para evitar este error he realizado una pequeña modificacion en el código del módulo.

Podéis consultar el repositorio y el fork realizado sobre el proyecto original en GitHub.

Fuentes

Comparte si te ha gustado

Autor:
Última actualización:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

De acuerdo con lo dispuesto en el Reglamento (UE) 2016/679 de 27 de abril de 2016, consiento que mis datos sean tratados bajo la responsabilidad de Oscar Gascón Arjol para recibir respuesta a consultas. publicación de comentarios del blog y que las conserve mientras haya un interés mutuo para ello. Me doy por informado que tengo derecho a revocar este consentimiento en cualquier momento y a ejercer los de acceso, rectificación, portabilidad y supresión de mis datos y los de limitación y oposición al tratamiento dirigiéndome por email a me@oscargascon.es. También estoy informado de que puedo reclamar ante la autoridad de control a www.agpd.es.