Configuring layouts in Zend Framework 2

This article looks out how you can set different layouts for modules, controllers or actions using Zend Framework 2, and how this can be achieved using module config files. 

Defining layouts individually

If you have a single layout used for the majority of your application, but have a couple of controllers or layouts that need a different one, then the solution below should be sufficient for your requirements. 

To achive this, simply register the new layout in your modules module.config.php file (you can place this in any module as the config files are merged, I would recommend placing this inside your Application module if it's not module-specific). 

return array( 'view_manager' => 
    array( 'template_map' => 
        array( 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', 
            'layout/login' => __DIR__ . '/../view/layout/login.phtml', 
            'layout/admin' => __DIR__ . '/../view/layout/admin.phtml' ), 
    ) 
);

Next add your layout file(s) into a 'layout' folder inside the 'view' folder for your module. For an example layout file checkout the Zend 2 skeleton application, in most cases your layout will contain the following line, which will output the contents of your view files:

<?php echo $this->content; ?>

Now that the layout file exists and you've registered in your config file, all that's left to do is assign the layout to an action or controller. To set it for the whole controller you could do it in the construct, otherwise set it in the individual action function like so (located inside your controller):

public function loginAction()
{
    $this->layout('layout/login');
}

Define all layouts in a config file

So the above technique works fine if you only need to override the default layout once or twice, but if you've got several layouts and you need to mix and match within different namespaces, controllers and actions, then it would be better if this could all go in a module config file. 

Evan Coury has written a handy piece of code for defining your layouts by module, we're going to build on this in the code below so that we can also configure layouts right down to actions, as well as setting defaults for the controller or namespace (/module). 

Place the following code inside a new 'Module.php' file inside a module folder titled 'CSActionLayouts':

namespace CSActionLayouts;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $sem = $e->getApplication()->getEventManager()->getSharedManager();

        $sem->attach( 'Zend\Mvc\Controller\AbstractController', 'dispatch', function($e)
        {
            $config = $e->getApplication()->getServiceManager()->get('config');
            $routeMatch = $e->getRouteMatch();
            $namespace = array_shift(explode('\\', $routeMatch->getParam('controller')));
            $controller = $e->getTarget();
            $controllerName = array_pop(explode('\\', $routeMatch->getParam('controller')));
            $actionName = strtolower($routeMatch->getParam('action'));

            // Use the layout assigned to the action
            if(isset($config['layouts'][$namespace]['controllers'][$controllerName]['actions'][$actionName]))
            {
                $controller->layout($config['layouts'][$namespace]['controllers'][$controllerName]['actions'][$actionName]);
            }
            // Use the controller default layout
            elseif(isset($config['layouts'][$namespace]['controllers'][$controllerName]['default']))
            {
                $controller->layout($config['layouts'][$namespace]['controllers'][$controllerName]['default']);
            }
            // Use the module default layout
            elseif(isset($config['layouts'][$namespace]['default']))
            {
                $controller->layout($config['layouts'][$namespace]['default']);
            }

        }, 10);
    }
}

The above code attaches a listener to the shared event manager so that on 'dispatch' it will get the config for the application (an accumulation of the config files in your modules), and check what layouts have been set against namespaces, controllers or actions. Action layouts take precendence over controllers, and controllers over namespaces. If none are set it will fall back to the higher level default. 

Now all you need to do is add the 'CSActionLayouts' to your list of modules to load in /config/application.config.php and then you can define which layouts are used for which namespaces, controllers or actions in your module config files.

Example configuration

As an example you might have a 'User' module for managing admins that can login. The module has an admin controller and you want:

  • a 'login' action that uses a 'login' layout
  • a default 'admin' layout for when users are logged in and are using the admin controller
  • a default module layout titled 'default' for users not logged in (or using any other controller)

Example module.config.php

All the below options are optional but demonstrate how defaults can be set for the namespace or controller, and how you can override the layout for a specific action.

return array(
'layouts' => array(
'User' => array(
'controllers' => array(
'Admin' => array(
'actions' => array(
'login' => 'layout/login'
),
'default' => 'layout/admin'
)
),
'default' => 'layout/default'
)
)
);

Source on BitBucket

View the code on Bitbucket.

Sign Up

NEXT: Auto Escaping View Variables Using Zend Framework and Doctrine 2

Looking at the escaping output, and how this can be achieved with Zend Framework and Doctrine 2.

comments powered by Disqus
Sign Up

Popular Tags

350x250

Need a web developer?

If you'd like to work with code synthesis on your next project get in touch via the contact page.