Cookbook
Setting module-specific Layouts
The following example shows how to set a template for the layout based on a
module name in a laminas-mvc based application. The example uses a listener that
listens on the
Laminas\Mvc\MvcEvent::EVENT_RENDER
event
and uses the
Laminas\Router\RouteMatch
object
to get the called controller from the current request.
Create Listener
Create a listener as a separate class, e.g.
module/Admin/src/Listener/LayoutListener.php
:
namespace Admin\Listener;
use Laminas\EventManager\AbstractListenerAggregate;
use Laminas\EventManager\EventManagerInterface;
use Laminas\Filter\FilterChain;
use Laminas\Filter\FilterInterface;
use Laminas\Filter\StringToLower;
use Laminas\Filter\Word\CamelCaseToDash;
use Laminas\Mvc\MvcEvent;
use Laminas\View\Resolver\TemplateMapResolver;
class LayoutListener extends AbstractListenerAggregate
{
/** @var TemplateMapResolver */
private $templateMapResolver;
/** @var FilterInterface */
private $filter;
public function __construct(TemplateMapResolver $templateMapResolver)
{
$this->templateMapResolver = $templateMapResolver;
$this->filter = (new FilterChain())
->attach(new CamelCaseToDash())
->attach(new StringToLower());
}
public function attach(EventManagerInterface $events, $priority = 1)
{
$this->listeners[] = $events->attach(
MvcEvent::EVENT_RENDER,
[$this, 'setLayout']
);
}
public function setLayout(MvcEvent $event) : void
{
// Get and check the route match object
$routeMatch = $event->getRouteMatch();
if (! $routeMatch) {
return;
}
// Get and check the parameter for current controller
$controller = $routeMatch->getParam('controller');
if (! $controller) {
return;
}
// Extract module name
$module = substr($controller, 0, strpos($controller, '\\'));
// Convert the module name from camel case to a lower string with dashes
$name = 'layout/' . $this->filter->filter($module);
// Has the resolver an entry / layout with the given name?
if (! $this->templateMapResolver->has($name)) {
return;
}
// Get root view model
$layoutViewModel = $event->getViewModel();
// Rendering without layout?
if ($layoutViewModel->terminate()) {
return;
}
// Change template
$layoutViewModel->setTemplate($name);
}
}
Register Listener
Extend the module class to register the listener, e.g.
module/Admin/Module.php
:
namespace Admin;
use Admin\Listener\LayoutListener;
use Laminas\Mvc\MvcEvent;
use Laminas\View\Resolver\TemplateMapResolver;
class Module
{
public function onBootstrap(MvcEvent $event) : void
{
$application = $event->getApplication();
/** @var TemplateMapResolver $templateMapResolver */
$templateMapResolver = $application->getServiceManager()->get(
'ViewTemplateMapResolver'
);
// Create and register layout listener
$listener = new LayoutListener($templateMapResolver);
$listener->attach($application->getEventManager());
}
// …
}
More information on registering module-specific listeners can be found in the documentation of laminas-mvc.
Add Template Scripts to the Configuration
Extend the configuration of a module to add the specific layout script, e.g.
module/Admin/config/module.config.php
:
return [
// Add the following array
'view_manager' => [
'template_map' => [
'layout/admin' => __DIR__ . '/../view/layout/admin.phtml',
],
],
// …
];
And in another module, e.g. module/Album/config/module.config.php
:
return [
// Add the following array
'view_manager' => [
'template_map' => [
'layout/album' => __DIR__ . '/../view/layout/layout-of-album.phtml',
],
],
// …
];
The name of the array key must follow the format layout/{module-name}
and the
value must contain the path to the layout file. The path and the filename can be
freely chosen.