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, zftoolIn 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_mapfor 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.phtmland
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/layoutin
module.config.phpin
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.phpfile, again attaching to the dispatch event and checking
which controller is being requested
Overriding at the controller level
I’ll first implement thesetEventManager()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. InModule.phpfor
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.
相关文章推荐
- php框架laravel学习 一 (环境搭建)
- php中按位取反~的理解
- 读书笔记:高性能PHP应用开发
- ubuntu用 tftp服务下载文件到2440开发板
- Ubuntu 配置tftp服务
- ThinkPHP与UCenter整合详解
- Zend Framework教程-入门相关
- zendframework1.0框架程手册
- ThinkPHP3.1新特性 多数据库操作的完善
- php安装mysql扩展,版本不一致的解决办法
- php int 与 datetime 转换
- php实现多城市切换特效
- (六)面向对象的设计原则之二
- ACM中关于Output Limit Exceeded和Time Limit Exceeded
- php正则表达式
- php多城市切换
- php flush类输出缓冲剖析
- FTP操作类
- PHP开发者应了解的24个库
- PHP 命名空间