Zend路由问题

Gus*_*avo 5 routing zend-framework

我已经阅读了有关路由和Zend文档的所有帖子,但我仍然无法解决这个问题.

我有一个包含两个模块的多语言应用程序:default和admin.语言选择工作正常(在Controller routeShutdown插件中),但我在配置路由器时遇到一些问题:

我想让这些URL工作:

/
/controller
/controller/action
/action                  (default controller)
/controller/param        (default action)
/admin
/admin/admin-controller
/admin/admin-controller/action
Run Code Online (Sandbox Code Playgroud)

并使用语言选择器,它将是:

/en
/en/controller
/en/controller/action
/en/action                  (default controller)
/en/controller/param        (default action)
/en/admin/admin-controller
/en/admin/admin-controller/action
Run Code Online (Sandbox Code Playgroud)

我把它添加到我的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'));    
Run Code Online (Sandbox Code Playgroud)

为了检查路由器如何解析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)
Run Code Online (Sandbox Code Playgroud)

这没关系.但是当我进入/ en/controller1时,我得到:

array
'lang' => string 'en' (length=2)
'module' => string 'controller1' (length=8)
'action' => string 'index' (length=5)
'controller' => string 'index' (length=5) 
Run Code Online (Sandbox Code Playgroud)

将模块设置为"controller1".如何告诉路由器为模块设置默认值?对于像/ en/controller/param这样的URL?(将模块和操作设置为默认值)

Tim*_*ain 6

我担心您需要稍微重新考虑一下您的URL方案,或者改变路由设置的方式,因为您已经遇到了ZF路由工作方式的两个限制.

首先,路由器不知道什么是有效的模块,控制器或动作; 它所做的只是将URL中的字符串与路径中的变量相匹配.它通过以相反的顺序连续检查每条路线,直到找到匹配为止.当你点击时/en/controller,它首先检查你的/:lang路线,这是不匹配的.然后检查/:lang/:module,哪个匹配,因为/:lang/:module匹配/任何/任何东西,除非你另有说明.

考虑到这一点,你将无法兼得:

/en/controller
/en/action
Run Code Online (Sandbox Code Playgroud)

除非您设置了一些限制,因为类似的URL /en/foo将始终与您最后定义的两个匹配.

如果你有相当少数的动作/控制器经常不会改变,最简单的方法是在两条路线中的第二条路线中硬编码一些可能的值,例如:

$router->addRoute('langmod', new Zend_Controller_Router_Route(
    '/:lang/:module', 
    array(
        'lang' => ':lang',
        'action' => 'index',
        'controller' => 'index'
    ),
    array(
        'module' => '(foo|bar|something)'
    )
));
Run Code Online (Sandbox Code Playgroud)

用有效的模块名称替换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' 
    )
));
Run Code Online (Sandbox Code Playgroud)

现在有一个控制器变量的默认值.如果我们假装这是唯一的路径,/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)
Run Code Online (Sandbox Code Playgroud)

这会给你这样的网址:

/en
/en/controller
/en/controller/action
/en/action
/en/controller/param
/en/admin/controller
/en/admin/controller/action
Run Code Online (Sandbox Code Playgroud)

这几乎就是你追求的目标.

ZF中的路由非常强大,您只需知道它的怪癖.