一)路由配置和视图文件路径
ZendFramework2项目的路由配置在config\module.config.php文件中:
[php] view plain copy
'router' => array(
'routes' => array(
'XXX' => array(
'type' => 'segment',
'options' => array(
'route' => '/YYY[/][:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'__NAMESPACE__' => 'ZZZ\Controller',
),
),
),
),
),
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
class InjectTemplateListener extends AbstractListenerAggregate
{
public function injectTemplate(MvcEvent $e)
{
//......
$template = $this->inflectName($module);
//......
$template .= '/';
//......
$template .= $this->inflectName($controller);
//......
$template .= '/' . $this->inflectName($action);
}
protected function inflectName($name)
{
if (!$this->inflector) {
$this->inflector = new CamelCaseToDashFilter();
}
$name = $this->inflector->filter($name);//filter函数会将字符串中“位置不是第一个”且“前面的字母是小写字母”的大写字母前面添加一个分隔符‘-’,即,如果$name=“TestTest”,那么该函数返回的就是“test-test”
return strtolower($name);
}
}
可见,如果模块、控制器或者action的名称拥有一个“位置不是第一个”且“前面的字母是小写字母”的大写字母的话,会导致视图文件的路径中出现‘-’分隔符!!!因此,当创建模块、控制器或者action的时候就需要特别注意在view目录下创建视图文件及其所在文件夹的时候要适时添加分隔符‘-’!!!
二)同模块配置多路由
只需要在config\module.config.php文件中配置相同“__NAMESPACE__”的路由即可:
[php] view plain copy
'router' => array(
'routes' => array(
'XXX' => array(
'type' => 'segment',
'options' => array(
'route' => '/YYY[/][:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'__NAMESPACE__' => 'ZZZ\Controller',
),
),
),
'AAA' => array(
'type' => 'segment',
'options' => array(
'route' => '/BBB[/][:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'__NAMESPACE__' => 'ZZZ\Controller',
),
),
),
),
),
如上配置,通过“http://....../YYY/......”和“http://....../BBB/......”访问的就都是ZZZ模块的控制器了!
三)多控制器配置
以上的配置就支持多控制器:
[php] view plain copy
'router' => array(
'routes' => array(
'XXX' => array(
'type' => 'segment',
'options' => array(
'route' => '/YYY[/][:controller][/:action][/:id]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'__NAMESPACE__' => 'ZZZ\Controller',
),
),
),
),
),
假设ZZZ\Controller目录下有AdminController和TestController两个控制器,则可以通过“http://....../YYY/admin/......”和“http://....../YYY/test/......”来分别访问这2个控制器!
三)同控制器多路由配置
要实现同控制器多路由配置,要将controller这个匹配项作为子路由,并且在主路由限定控制器,就可以实现,配置如下:
[php] view plain copy
'XXX' => array(
'type' => 'Literal',
'options' => array(
'route' => '/YYY',
'defaults' => array(
'__NAMESPACE__' => 'ZZZ\Controller',
'controller' => 'WWW',
),
),
'may_terminate' => true,
'child_routes' => array(
'EEE1' => array(
'type' => 'Segment',
'options' => array(
'route' => '/FFF1[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
'EEE2' => array(
'type' => 'Segment',
'options' => array(
'route' => '/FFF2[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
按以上配置,由于在主路由中限制了控制器WWWController,所以通过“http://.../YYY/FFF1/...”和“http://.../YYY/FFF2/...”就都是访问ZZZ模块的WWWController了!另外,由于有了子路由,通过mvc过程中的MVCEvent,$MVCEventObject->getRouteMatch()->getMatchedRouteName();获取到的路由名称是“XXX/EEE1”或者“XXX/EEE2”。
同样的方法,也可以实现统一action的不同路由配置。