手记

(转)ZendFramework2学习笔记 视图文件路径,多控制器路由,同模块或同控制器的多路

一)路由配置和视图文件路径

    ZendFramework2项目的路由配置在config\module.config.php文件中:

[php] view plain copy 

  1. 'router' => array(  

  2.      'routes' => array(  

  3.          'XXX' => array(  

  4.              'type'    => 'segment',  

  5.              'options' => array(  

  6.                  'route'    => '/YYY[/][:controller][/:action][/:id]',  

  7.                  'constraints' => array(  

  8.                      'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',  

  9.                      'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',  

  10.                      'id'     => '[0-9]+',  

  11.                  ),  

  12.                  'defaults' => array(  

  13.                      '__NAMESPACE__' => 'ZZZ\Controller',  

  14.                  ),  

  15.                    

  16.              ),  

  17.          ),  

  18.      ),  

  19. ),  

1)路由名称XXX:

    在layout.phtml和view.phtml等视图文件中,经常会用到“$this->url(aaa);”语句来设置超链接,其中aaa就是路由名称。这个aaa必须在某个模块的config\module.config.php中设置过,否则,“$this->url(aaa);”这句在运行时会出现“没有处理的异常”错误!

    还有需要注意的是,对于mvc过程中的MVCEvent,通过$MVCEventObject->getRouteMatch()->getMatchedRouteName();获取到的路由名称是这个XXX,而不是url中的YYY。

2)YYY区分大小写,例如:如果YYY=“admin”,那么访问“http://.../Admin/...”会出现“404页面未找到”错误!但是,匹配项controller和action不区分大小写,即,“http://.../admin/ADMIN/INDEX/...”和“http://.../admin/admin/index/...”都能成功访问到AdminController控制器的名为index的action!

3)ZZZ是模块名称,即ZZZ\Controller是模块的控制器所在路径(“\module\ZZZ\src\ZZZ\Controller\”)!

4)mvc过程怎样获取视图文件路径:

    ZendFramework2需要读取视图文件来render网页的时候,会使用模块、控制器和action的名称的“小写”字符串来拼接出.phtml视图文件路径,例如:假设Admin模块有一个TestController控制器,TestController控制器有一个doAction的action,那么,ZendFramework2是读取view\admin\test\do.phtml这个视图文件来render网页。

5)模块、控制器和action名称的“小陷阱”

    先看看ZendFramework2拼接视图文件路径的代码,如下:

[php] view plain copy 

  1. class InjectTemplateListener extends AbstractListenerAggregate  

  2. {  

  3.     public function injectTemplate(MvcEvent $e)  

  4.     {  

  5.         //......  

  6.           

  7.         $template   = $this->inflectName($module);  

  8.   

  9.         //......  

  10.         $template .= '/';  

  11.         //......  

  12.   

  13.         $template  .= $this->inflectName($controller);  

  14.   

  15.         //......  

  16.       

  17.         $template .= '/' . $this->inflectName($action);  

  18.     }  

  19.   

  20.     protected function inflectName($name)  

  21.     {  

  22.         if (!$this->inflector) {  

  23.             $this->inflector = new CamelCaseToDashFilter();  

  24.         }  

  25.         $name = $this->inflector->filter($name);//filter函数会将字符串中“位置不是第一个”且“前面的字母是小写字母”的大写字母前面添加一个分隔符‘-’,即,如果$name=“TestTest”,那么该函数返回的就是“test-test”  

  26.         return strtolower($name);  

  27.     }  

  28. }  

    可见,如果模块、控制器或者action的名称拥有一个“位置不是第一个”且“前面的字母是小写字母”的大写字母的话,会导致视图文件的路径中出现‘-’分隔符!!!因此,当创建模块、控制器或者action的时候就需要特别注意在view目录下创建视图文件及其所在文件夹的时候要适时添加分隔符‘-’!!!

二)同模块配置多路由

    只需要在config\module.config.php文件中配置相同“__NAMESPACE__”的路由即可:

[php] view plain copy 

  1. 'router' => array(  

  2.      'routes' => array(  

  3.          'XXX' => array(  

  4.              'type'    => 'segment',  

  5.              'options' => array(  

  6.                  'route'    => '/YYY[/][:controller][/:action][/:id]',  

  7.                  'constraints' => array(  

  8.                      'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',  

  9.                      'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',  

  10.                      'id'     => '[0-9]+',  

  11.                  ),  

  12.                  'defaults' => array(  

  13.                      '__NAMESPACE__' => 'ZZZ\Controller',  

  14.                  ),  

  15.                    

  16.              ),  

  17.          ),  

  18.          'AAA' => array(  

  19.              'type'    => 'segment',  

  20.              'options' => array(  

  21.                  'route'    => '/BBB[/][:controller][/:action][/:id]',  

  22.                  'constraints' => array(  

  23.                      'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',  

  24.                      'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',  

  25.                      'id'     => '[0-9]+',  

  26.                  ),  

  27.                  'defaults' => array(  

  28.                      '__NAMESPACE__' => 'ZZZ\Controller',  

  29.                  ),  

  30.                    

  31.              ),  

  32.          ),  

  33.      ),  

  34. ),  

    如上配置,通过“http://....../YYY/......”和“http://....../BBB/......”访问的就都是ZZZ模块的控制器了!

三)多控制器配置

    以上的配置就支持多控制器:

[php] view plain copy 

  1. 'router' => array(  

  2.      'routes' => array(  

  3.          'XXX' => array(  

  4.              'type'    => 'segment',  

  5.              'options' => array(  

  6.                  'route'    => '/YYY[/][:controller][/:action][/:id]',  

  7.                  'constraints' => array(  

  8.                      'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',  

  9.                      'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',  

  10.                      'id'     => '[0-9]+',  

  11.                  ),  

  12.                  'defaults' => array(  

  13.                      '__NAMESPACE__' => 'ZZZ\Controller',  

  14.                  ),  

  15.                    

  16.              ),  

  17.          ),  

  18.      ),  

  19. ),  

    假设ZZZ\Controller目录下有AdminController和TestController两个控制器,则可以通过“http://....../YYY/admin/......”和“http://....../YYY/test/......”来分别访问这2个控制器!

三)同控制器多路由配置

    要实现同控制器多路由配置,要将controller这个匹配项作为子路由,并且在主路由限定控制器,就可以实现,配置如下:

[php] view plain copy 

  1. 'XXX' => array(  

  2.     'type'    => 'Literal',  

  3.     'options' => array(  

  4.         'route'    => '/YYY',  

  5.         'defaults' => array(  

  6.             '__NAMESPACE__' => 'ZZZ\Controller',  

  7.             'controller'    => 'WWW',  

  8.         ),  

  9.     ),  

  10.     'may_terminate' => true,  

  11.     'child_routes' => array(  

  12.         'EEE1' => array(  

  13.             'type'    => 'Segment',  

  14.             'options' => array(  

  15.                 'route'    => '/FFF1[/][:action][/:id]',  

  16.                 'constraints' => array(  

  17.                     'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',  

  18.                 ),  

  19.                 'defaults' => array(  

  20.                 ),  

  21.             ),  

  22.         ),  

  23.         'EEE2' => array(  

  24.             'type'    => 'Segment',  

  25.             'options' => array(  

  26.                 'route'    => '/FFF2[/][:action][/:id]',  

  27.                 'constraints' => array(  

  28.                     'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',  

  29.                 ),  

  30.                 'defaults' => array(  

  31.                 ),  

  32.             ),  

  33.         ),  

  34.     ),  

  35. ),  

    按以上配置,由于在主路由中限制了控制器WWWController,所以通过“http://.../YYY/FFF1/...”和“http://.../YYY/FFF2/...”就都是访问ZZZ模块的WWWController了!另外,由于有了子路由,通过mvc过程中的MVCEvent,$MVCEventObject->getRouteMatch()->getMatchedRouteName();获取到的路由名称是“XXX/EEE1”或者“XXX/EEE2”。


    同样的方法,也可以实现统一action的不同路由配置。

原文链接:http://www.apkbus.com/blog-228660-63578.html

0人推荐
随时随地看视频
慕课网APP