您的位置:首页 > 编程语言 > PHP开发

Change Layout in Controllers and Actions in Zend Framework 2

2015-08-09 11:53 639 查看


Change Layout in Controllers and Actions in Zend Framework 2

25 Jun 2014 6 Comments Permalink Tags: bootstrap, dispatch, eventmanager, init, layouts, modules, zftool

In Zend Framework 2, if you want to change the layout just for one action or for every action in a controller, how do you do it? How do you do it without overriding the layout for every action throughout
the entire application?

In today’s post, based on an
excerpt from Zend Framework 2 for Beginners, we see how to achieve both of these requirements.

Thanks to GeeH, over in #zftalk, for providing
corrections to the earlier draft of this post.
Zend Framework 2 implements the
2-Step View pattern, which allows for one set of view templates to handle logic such as headers, footers, sidebars and navigation blocks, logic not specific to any one action be kept separate from the view templates
which render the content of a specific action.
If you’re creating your Zend Framework 2 projects using
ZFTool, or basing them off of the ZF2 Skeleton
App code, then you’ll know that the Application module contains a template alias in
template_map
for the default layout template file.
If not, here’s the definition:
'view_manager' => array(
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
),
),

When an application’s called, the view rendered by the dispatched action, will be rendered within
module/Application/view/layout/layout.phtml
and
the combined result will be displayed, assuming you’ve not disabled layouts, which we’ll cover another time.
For the most part, that works fine. But what if you want to use different layouts per/module, per/controller, evenper/action? Zend Framework 2 makes it easy to do this. In today’s
post I’m going so show you three ways to do it, all varying in complexity.


1. Override the default layout in your module

The simplest is to override
layout/layout
in
module.config.php
in
our module. So long as our module’s activated, after Application, then your module’s preferences will overwrite those in Application, making it the new default layout.
To do so, in your module’s module.config.php file, add or integrate the configuration above, specifying the path to a new layout file.


2. Override the layout per/action

But doing this replaces the layout globally, for every request. If we wanted to override the layout on an as-needed basis instead, we can call the controller’s
layout()
function,
in an action, and pass a template name or alias to it.
Here’s an example of overriding the layout for the index action.
public function indexAction()
{
$this->layout('layout/generic');
}

Assuming that we had a template alias, called ‘layout/generic’, defined the template_map for our module, then it would be rendered, instead of either the default or overridden layout template.


3. Override the layout per/controller

But if we call it in our action, the layout will only be overridden for that specific action. What if we want to override it for every action in the controller? There’s a couple of ways you can do this:

You can define the
setEventManager()
function in the Controller, attaching to the dispatch event
You can implement the init function in the module’s
Module.php
file, again attaching to the dispatch event and checking
which controller is being requested

Overriding at the controller level

I’ll first implement the
setEventManager()
function in the Controller. In your controller add in
the following use statement:
use Zend\EventManager\EventManagerInterface;

Then add in the following function.
public function setEventManager(EventManagerInterface $events)
{
parent::setEventManager($events);
$controller = $this;
$events->attach('dispatch', function ($e) use ($controller) {
$controller->layout('layout/generic');
}, 100);
}

What we’ve done here, is to get access to the EventManager and attach a closure which will listen for the dispatch event, by specifying ‘dispatch’ as the first argument, a closure as the second and the event
priority as the third.
The higher the priority the more important that event is. By passing the current controller object to the closure we can call the layout function on it, specifying the same template alias as before.
Now, when any action of this controller is dispatched, the closure will be executed, overriding the layout to the one we’ve specified. Actions in any other controller, in any other module, will use the default
layout template as normal.

Overriding at the module level

Finally, let’s look at overriding the controller at the module level. Effectively the code we’ll create now is just the same as the last example, it’s just the location that’s different. In
Module.php
for
your module, add the code below and let’s step through it.
use Zend\ModuleManager\ModuleManager;

public function init(ModuleManager $manager)
{
$events = $manager->getEventManager();
$sharedEvents = $events->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
$controller = $e->getTarget();
if (get_class($controller) == 'Generic\Controller\IndexController')         {
$controller->layout('layout/generic');
}
}, 100);
}

We place the code here because the
init()
function, if defined, is called on every page request.
For more information on the available Module options, check
out the manual.
What it does is to get access to the EventManager and attach a listener to the dispatch event as before, using a closure, with one small difference.
As we’re at the module, we have to add in a check to determine which controller’s handling the request. If it’s the right one, then the layout function is again called. If not, the original layout template
is rendered.
And there you have it. Three simple ways to override layouts in your Zend Framework 2 modules.
Do you change layouts in your modules this way, or do you take a different approach? Share your approach in the comments.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: