zend framework2 的controller内如何直接返回不带模板的页面

 

ZendFramework2学习笔记 静态配置layout模板和动态设置layout模板

分类: ZendFramework2
 

目录(?)[+]

 

1)静态配置layout

ZendFramework2项目在启动过程中,会读取配置文件中的layout配置。

layout配置默认放在Application模块的config\module.config.php配置文件中的‘view_manager’项中,如下:

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 'view_manager' => array(  
  2.         'layout'                   => 'layout/layout',  
  3. ),  
手动创建的zf2项目的‘view_manager’项中可能没有‘layout’这个子项,这时候需要我们手动添加“'layout'=>'layout/layout',”。很奇怪,为什么zf2项目的‘view_manager’项中没有‘layout’这个子项也能够自动加载\Module\Application\view\layout\layout.phtml呢?原因就在于ViewManager中已经写死了默认值,如果没有配置‘layout’就采用默认值'layout/layout',如下:

 

 

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. class ViewManager extends AbstractListenerAggregate  
  2. {  
  3.     public function getLayoutTemplate()  
  4.     {  
  5.         $layout = 'layout/layout';  
  6.         if (isset($this->config['layout'])) {  
  7.             $layout = $this->config['layout'];  
  8.         }  
  9.         return $layout;  
  10.     }  
  11. }  
除了Application模块,layout配置也可以放在其他模块的config\module.config.php配置文件中的‘view_manager’项中。

 

 

如果Application模块和其他模块中都配置了layout项的话,根据各个模块的加载顺序,后加载的模块的layout配置会覆盖掉先加载的模块的layout配置,即zf2会采用最后一个加载的模块的layout配置。如下:

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. class ConfigListener extends AbstractListener implements  
  2.     ConfigMergerInterface,  
  3.     ListenerAggregateInterface  
  4. {  
  5.     public function onMergeConfig(ModuleEvent $e)  
  6.     {  
  7.         foreach ($this->configs as $config) {//遍历各个模块的配置  
  8.             $this->mergedConfig = ArrayUtils::merge($this->mergedConfig, $config);//合并各个模块的配置  
  9.         }  
  10.   
  11.         return $this;  
  12.     }  
  13. }  
  14.   
  15. abstract class ArrayUtils  
  16. {  
  17.     public static function merge(array $a, array $b, $preserveNumericKeys = false)  
  18.     {  
  19.         foreach ($b as $key => $value) {  
  20.             if (array_key_exists($key, $a)) {  
  21.                 if (is_int($key) && !$preserveNumericKeys) {  
  22.                     $a[] = $value;  
  23.                 } elseif (is_array($value) && is_array($a[$key])) {  
  24.                     $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys);  
  25.                 } else {  
  26.                     $a[$key] = $value;//相同的配置项,后者的value会覆盖前者的value  
  27.                 }  
  28.             } else {  
  29.                 $a[$key] = $value;  
  30.             }  
  31.         }  
  32.   
  33.         return $a;  
  34.     }  
  35. }  
模块的加载顺序是根据应用配置文件\config\application.config.php中的‘modules’项来的:

 

 

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 'modules' => array(  
  2.     'Application',  
  3.     'User',  
  4.     'Admin',  
  5. ),  
按照上面的配置,模块的加载顺序就是'Application'->'User'->'Admin',所以,如果\module\Admin\config\module.config.php中的‘view_manager’项中配置了‘layout’子项,则zf2会采用Admin模块中的这个layout配置。

 

 

既然zf2对layout配置的获取是根据模块的加载顺序采用最后一个,那么zf2对于layout的.phtml文件的获取是怎么样的?
1)zf2会按照模块的加载顺序,在各个模块的view目录下查找最后采用的layout配置对应的.phtml文件;
2)zf2采用最后一个从模块的view目录下获取的layout对应的.phtml文件。
例如:上面例子中,zf2采用了Admin模块的layout配置“layout/layout”,该layout配置对应的.phtml文件是模块的view目录下的\layout\layout.phtml文件,如果'Application'和'User'这2个模块的view目录下都有\layout\layout.phtml文件,而'Admin'模块的view目录下没有\layout\layout.phtml文件,那么,根据模块的加载顺序'Application'->'User'->'Admin',zf2最后采用的layout文件就是'User'模块的view目录下的\layout\layout.phtml文件。

因此,如果采用静态配置layout,zf2项目就只有一个layout,这样对实际项目开发而言可能不够。例如,一个商城网站可能会有“顾客”、“店铺主”和“管理员”这三种角色,“顾客”可能需要一个能浏览商城的layout和一个能付款收货的个人中心layout,“店铺主”可能需要能管理货物上下架、收款发货的店铺管理layout,“管理员”可能需要能查看商城所有交易信息的商城管理layout。因此,就需要动态设置layout。

 

2)动态设置layout

ZendFramework2项目的mvc过程中,会有一个MvcEvent对象贯穿始终,通过该对象,可以动态设置layout:

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. $viewModel = $e->getViewModel();//($e instanceof MvcEvent == true);  
  2. if ($viewModel)  
  3.     $viewModel->setTemplate("layout/layout");  
一个商城网站,像“顾客”、“店铺主”和“管理员”这三种角色所需要的4种layout可以通过不同url来区分,例如:浏览商品可能是http://xxx/goods/xxxxxxx这样的url,顾客中心可能是http://xxx/customer/xxxxxxx这样的url,店铺后台管理可能是http://xxx/shopowner/xxxxxxx,管理后台可能是http://xxx/admin/xxxxxxx这样的url。

 

 

假定这样配置路由:

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 'goods' => array(  
  2.            'type'    => 'segment',  
  3.            'options' => array(  
  4.                'route'    => '/goods[/][:action][/:id]',  
  5.                'constraints' => array(  
  6.                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',  
  7.                    'id'     => '[0-9]+',  
  8.                ),  
  9.                'defaults' => array(  
  10.                    'controller' => 'Goods\Controller\Goods',  
  11.                    'action'     => 'index',  
  12.                ),  
  13.            ),  
  14.        ),  
  15.        'customer' => array(  
  16.            'type'    => 'segment',  
  17.            'options' => array(  
  18.                'route'    => '/customer[/][:action][/:id]',  
  19.                'constraints' => array(  
  20.                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',  
  21.                    'id'     => '[0-9]+',  
  22.                ),  
  23.                'defaults' => array(  
  24.                    'controller' => 'Customer\Controller\Customer',  
  25.                    'action'     => 'admin',  
  26.                ),  
  27.            ),  
  28.        ),  
  29. 'shopowner' => array(  
  30.            'type'    => 'segment',  
  31.            'options' => array(  
  32.                'route'    => '/shopowner[/][:action][/:id]',  
  33.                'constraints' => array(  
  34.                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',  
  35.                    'id'     => '[0-9]+',  
  36.                ),  
  37.                'defaults' => array(  
  38.                    'controller' => 'Shopowner\Controller\Shopowner',  
  39.                    'action'     => 'admin',  
  40.                ),  
  41.            ),  
  42.        ),  
  43. 'admin' => array(  
  44.            'type'    => 'segment',  
  45.            'options' => array(  
  46.                'route'    => '/admin[/][:action][/:id]',  
  47.                'constraints' => array(  
  48.                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',  
  49.                    'id'     => '[0-9]+',  
  50.                ),  
  51.                'defaults' => array(  
  52.                    'controller' => 'Admin\Controller\Admin',  
  53.                    'action'     => 'admin',  
  54.                ),  
  55.            ),  
  56.        ),  
这样,就可以通过route名称来区分url了。

 

 

然后,在Application模块的\view\layout\目录下面可以分别放置4个layout文件:goods.phtml、customer.phtml、shopowner.phtml和admin.phtml。

ZendFramework2项目的启动过程,依次会触发loadModules、loadModule、bootstrap、route、dispatch......等事件,其中对layout配置的读取是在loadModule事件中完成的,而对url的路由解析是在route事件中完成的,因此,可以设置一个route事件的listener,在该listener中完成动态设置layout。

Application模块Module.php的onBootstrap是bootstrap事件被触发后最后一个被执行的listener,可以在该函数中attach一个route事件的listener:

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. class Module  
  2. {  
  3.     public function onBootstrap(MvcEvent $e)  
  4.     {  
  5.         $eventManager        = $e->getApplication()->getEventManager();  
  6.         $moduleRouteListener = new ModuleRouteListener();  
  7.         $moduleRouteListener->attach($eventManager);  
  8.   
  9.         $eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRoute'), -9000);//attach一个route事件的listener  
  10.     }  
  11. }  
在onRoute函数中就可以根据route的不同名称来设置不同的layout了:

 

 

 

[php] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. class Module  
  2. {  
  3.     public function onRoute(MvcEvent $e)  
  4.     {  
  5.         $route = $e->getRouteMatch()->getMatchedRouteName();  
  6.         if ($route == 'user')//顾客个人中心  
  7.             $e->getViewModel()->setTemplate("layout/customer");  
  8.         else if ($route == 'shopowner')//店铺主管理后台  
  9.             $e->getViewModel()->setTemplate("layout/shopowner");  
  10.         else if ($route == 'admin')//管理员后台  
  11.             $e->getViewModel()->setTemplate("layout/admin");  
  12.         else//浏览商品  
  13.             $e->getViewModel()->setTemplate("layout/goods");  
  14.     }  
  15. }  
  16.    
posted @ 2015-10-30 15:24  LAOS  阅读(346)  评论(0编辑  收藏  举报