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

来源:互联网 发布:淘宝网店开店物流工具 编辑:程序博客网 时间:2024/06/11 09:31

1)静态配置layout

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

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

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

class ViewManager extends AbstractListenerAggregate{    public function getLayoutTemplate()    {        $layout = 'layout/layout';        if (isset($this->config['layout'])) {            $layout = $this->config['layout'];        }        return $layout;    }}
除了Application模块,layout配置也可以放在其他模块的config\module.config.php配置文件中的‘view_manager’项中。

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

class ConfigListener extends AbstractListener implements    ConfigMergerInterface,    ListenerAggregateInterface{    public function onMergeConfig(ModuleEvent $e)    {        foreach ($this->configs as $config) {//遍历各个模块的配置            $this->mergedConfig = ArrayUtils::merge($this->mergedConfig, $config);//合并各个模块的配置        }        return $this;    }}abstract class ArrayUtils{    public static function merge(array $a, array $b, $preserveNumericKeys = false)    {        foreach ($b as $key => $value) {            if (array_key_exists($key, $a)) {                if (is_int($key) && !$preserveNumericKeys) {                    $a[] = $value;                } elseif (is_array($value) && is_array($a[$key])) {                    $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys);                } else {                    $a[$key] = $value;//相同的配置项,后者的value会覆盖前者的value                }            } else {                $a[$key] = $value;            }        }        return $a;    }}
模块的加载顺序是根据应用配置文件\config\application.config.php中的‘modules’项来的:

    'modules' => array(        'Application',        'User',        'Admin',    ),
按照上面的配置,模块的加载顺序就是'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:

$viewModel = $e->getViewModel();//($e instanceof MvcEvent == true);if ($viewModel)    $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。

假定这样配置路由:

     'goods' => array(                 'type'    => 'segment',                 'options' => array(                     'route'    => '/goods[/][:action][/:id]',                     'constraints' => array(                         'action' => '[a-zA-Z][a-zA-Z0-9_-]*',                         'id'     => '[0-9]+',                     ),                     'defaults' => array(                         'controller' => 'Goods\Controller\Goods',                         'action'     => 'index',                     ),                 ),             ),             'customer' => array(                 'type'    => 'segment',                 'options' => array(                     'route'    => '/customer[/][:action][/:id]',                     'constraints' => array(                         'action' => '[a-zA-Z][a-zA-Z0-9_-]*',                         'id'     => '[0-9]+',                     ),                     'defaults' => array(                         'controller' => 'Customer\Controller\Customer',                         'action'     => 'admin',                     ),                 ),             ),     'shopowner' => array(                 'type'    => 'segment',                 'options' => array(                     'route'    => '/shopowner[/][:action][/:id]',                     'constraints' => array(                         'action' => '[a-zA-Z][a-zA-Z0-9_-]*',                         'id'     => '[0-9]+',                     ),                     'defaults' => array(                         'controller' => 'Shopowner\Controller\Shopowner',                         'action'     => 'admin',                     ),                 ),             ),     'admin' => array(                 'type'    => 'segment',                 'options' => array(                     'route'    => '/admin[/][:action][/:id]',                     'constraints' => array(                         'action' => '[a-zA-Z][a-zA-Z0-9_-]*',                         'id'     => '[0-9]+',                     ),                     'defaults' => array(                         'controller' => 'Admin\Controller\Admin',                         'action'     => 'admin',                     ),                 ),             ),
这样,就可以通过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:

class Module{    public function onBootstrap(MvcEvent $e)    {        $eventManager        = $e->getApplication()->getEventManager();        $moduleRouteListener = new ModuleRouteListener();        $moduleRouteListener->attach($eventManager);        $eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRoute'), -9000);//attach一个route事件的listener    }}
在onRoute函数中就可以根据route的不同名称来设置不同的layout了:

class Module{    public function onRoute(MvcEvent $e)    {        $route = $e->getRouteMatch()->getMatchedRouteName();        if ($route == 'user')//顾客个人中心            $e->getViewModel()->setTemplate("layout/customer");        else if ($route == 'shopowner')//店铺主管理后台            $e->getViewModel()->setTemplate("layout/shopowner");        else if ($route == 'admin')//管理员后台            $e->getViewModel()->setTemplate("layout/admin");        else//浏览商品            $e->getViewModel()->setTemplate("layout/goods");    }} 










0 0
原创粉丝点击