我已阅读有关路由和Zend文档的所有帖子,但我仍无法解决此问题。
我有一个包含两个模块的多语言应用程序:default和admin。语言选择工作正常(在Controller routeShutdown插件中),但我在配置路由器时遇到一些问题:
我希望这些网址有效:
/
/controller
/controller/action
/action (default controller)
/controller/param (default action)
/admin
/admin/admin-controller
/admin/admin-controller/action
并使用语言选择器:
/en
/en/controller
/en/controller/action
/en/action (default controller)
/en/controller/param (default action)
/en/admin/admin-controller
/en/admin/admin-controller/action
我将此添加到我的bootstap文件(index.php):
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->removeDefaultRoutes();
$router->addRoute('langmodcontrolleraction',
new Zend_Controller_Router_Route('/:lang/:module/:controller/:action',
array('lang' => ':lang'))
);
$router->addRoute('langmodcontroller',
new Zend_Controller_Router_Route('/:lang/:module/:controller',
array('lang' => ':lang',
'action' => 'index'))
);
$router->addRoute('langmod',
new Zend_Controller_Router_Route('/:lang/:module',
array('lang' => ':lang',
'action' => 'index',
'controller' => 'index'))
);
$router->addRoute('lang',
new Zend_Controller_Router_Route('/:lang',
array('lang' => ':lang',
'action' => 'index',
'controller' => 'index',
'module' => 'default'))
);
$frontController->setControllerDirectory(array(
'default'=>BASE_PATH.'app/modules/default/controllers',
'admin'=>BASE_PATH.'app/modules/admin/controllers'));
为了检查路由器如何解析URL,我在routeShutdown插件中添加了一个var_dump:
输入 / en ,我得到:
array
'lang' => string 'en' (length=2)
'action' => string 'index' (length=5)
'controller' => string 'index' (length=5)
'module' => string 'default' (length=7)
没关系。但是当我进入 / en / controller1 时,我得到:
array
'lang' => string 'en' (length=2)
'module' => string 'controller1' (length=8)
'action' => string 'index' (length=5)
'controller' => string 'index' (length=5)
将模块设置为“controller1”。如何告诉路由器为模块设置默认值?对于像/ en / controller / param这样的URL? (将模块和操作设置为默认值)
答案 0 :(得分:6)
我担心您需要重新考虑一下您的网址方案,或者更改路由的设置方式,因为您已经遇到了ZF路由工作方式的两个限制。
首先,路由器不知道什么是有效的模块,控制器或动作;它所做的只是将URL中的字符串与路径中的变量相匹配。它通过以相反的顺序连续检查每条路线来完成此操作,直到找到匹配为止。当您点击/en/controller
时,它会首先检查您的/:lang
路线,该路线不匹配。然后检查/:lang/:module
,它将匹配,因为/:lang/:module
将匹配/任何/任何东西,除非你另有说明。
考虑到这一点,你将无法兼得:
/en/controller
/en/action
除非您设置了一些限制,因为/en/foo
之类的网址将始终与您最后定义的两个匹配。
如果您的动作/控制器数量相对较少,而且经常不会改变,最简单的方法是对两条路线中的第二条路线的某些可能值进行硬编码,例如:
$router->addRoute('langmod', new Zend_Controller_Router_Route(
'/:lang/:module',
array(
'lang' => ':lang',
'action' => 'index',
'controller' => 'index'
),
array(
'module' => '(foo|bar|something)'
)
));
用有效的模块名称替换foo,bar等。现在,当您点击/en/controller1
时,它将不匹配此路由,因为controller1与为:module变量定义的正则表达式模式不匹配。然后,您需要单独的/:lang/:controller
路线(或可能/:lang/:controller/:action
)才能匹配。
您询问了如何为某些变量设置默认值。实际上你已经在你的一些路由中执行了这个操作,但是对于控制器/模块来说,你的希望方式不会很好。如果我们采用你的langmodcontroller路由并将其更改为:
$router->addRoute('langmodcontroller',new Zend_Controller_Router_Route(
'/:lang/:module/:controller',
array(
'lang' => ':lang',
'controller' => 'index'
'action' => 'index'
)
));
现在有一个控制器变量的默认值。如果我们假装这是唯一的路径,那么/en/blog
的请求现在将与此匹配,并将请求参数设置为lang = en,module = blog,controller = index,action = index。 /en/blog/index/foo
也会匹配这条路线,并会给你module = blog,controller = index,action = foo。但请注意,即使控制器=索引,您仍然需要在URL中。所以第二个限制就是你总是需要URL中的变量(即使它被设置为你的默认值),只要你有一些不是默认值的东西。
考虑到这些限制,我建议你选择这样的东西(按此顺序定义):
/:lang/:controller/:action/ (with 'index' defaults for controller and action)
/:lang/:action (with 'action' restricted to some predefined values)
/:lang/admin/:controller/:action (with 'admin' as a string in the URL, and :module set to 'admin' as the default)
这会为您提供如下网址:
/en
/en/controller
/en/controller/action
/en/action
/en/controller/param
/en/admin/controller
/en/admin/controller/action
这就是你所追求的。
ZF中的路由非常强大,您只需知道它的怪癖。