Zend路由问题 [英] Zend Routing problems

查看:71
本文介绍了Zend路由问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了有关路由和Zend文档的所有文章,但仍然无法解决此问题。

I've read all posts about routing and Zend Documentation but I still can't solve this issue.

我有一个带有两个模块的多语言应用程序:默认和管理员。语言选择工作正常(在Controller routeShutdown插件中),但是在配置路由器时遇到一些问题:

I have a multi-language application with two modules: default and admin. The language selection is working fine (in a Controller routeShutdown Plugin), but I have some problems configuring the router:

我希望这些URL工作正常:

I want to have these URL working:

/
/controller
/controller/action
/action                  (default controller)
/controller/param        (default action)
/admin
/admin/admin-controller
/admin/admin-controller/action

并使用语言选择器将是:

and using the language selector it would be:

/en
/en/controller
/en/controller/action
/en/action                  (default controller)
/en/controller/param        (default action)
/en/admin/admin-controller
/en/admin/admin-controller/action

我已添加这到我的引导文件(index.php):

I added this to my bootstap file (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:

In order to check how the router is parsing the URL, I added a var_dump to the routeShutdown plugin:

输入 / en ,我得到:

array
'lang' => string 'en' (length=2)
'action' => string 'index' (length=5)
'controller' => string 'index' (length=5)
'module' => string 'default' (length=7)

可以。但是当我输入 / en / controller1 时,我得到:

which is OK. But when I enter to /en/controller1 I get:

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? (将模块和操作设置为默认值)

It is setting module to "controller1". How can I tell the router to set the default value to the module? And for an URL like /en/controller/param? (setting module and action to default)

推荐答案

恐怕您需要重新考虑一下URL方案,或者更改路由的设置方式,因为您遇到了ZF路由工作方式的两个限制。

I'm afraid you're going to need to rethink your URL scheme a little, or change the way your routes are setup, as you've hit two limitations of the way ZF's routing works.

第一个是路由器不知道什么是或不是有效的模块,控制器或动作;它所做的只是将URL中的字符串与路由中的变量匹配。它以相反的顺序依次检查每个路由,直到找到匹配为止。当您按下 / en / controller 时,它将首先检查您的 /:lang 路线,该路线不匹配。然后,它检查将匹配的 /:lang /:module ,因为 /:lang /:module 将匹配/

The first is that the router has no knowledge of what is or isn't a valid module, controller or action; all it does is match the strings in the URL to variables in the route. It does this by checking each route in succession, in reverse order, until it finds a match. When you hit /en/controller, it first checks your /:lang route, which won't match. It then checks /:lang/:module, which will match, because /:lang/:module will match /anything/anything unless you tell it otherwise.

考虑到这一点,您将无法同时拥有两者:

With that in mind you won't be able to have both:

/en/controller
/en/action

除非您设置一些限制,否则像 / en / foo 这样的URL始终与您最后定义的两个URL匹配。

unless you set some restrictions, as a URL like /en/foo will always be matched by whichever of the two you define last.

如果您的动作/控制器数量很少,并且不经常更改,那么解决此问题的最简单方法是为两条路线的第二条路线硬编码一些可能的值,例如:

If you have a fairly small number of actions/controllers that don't often change, the simplest way around this is to hardcode in some possible values for the 2nd of the two routes, e.g.:

$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变量定义的regexp模式不匹配。然后,您将需要一个单独的 /:lang /:controller 路由(或者可能是 /:lang /:controller /:action

replace foo, bar etc. with valid module names. Now when you hit /en/controller1 it won't match this route because controller1 doesn't match the regexp pattern defined for the :module variable. You would then need a separate /:lang/:controller route (or possibly /:lang/:controller/:action) for it to match instead.

您问如何为某些变量设置默认值。实际上,您已经在一些路线中执行了此操作,但是对于控制器/模块,并不能完全按照您希望的方式工作。如果我们采用您的langmodcontroller路由并将其更改为:

You asked how you set a default value for some of the variables. You are actually already doing this with the action in a few of your routes, but for controller/module won't quite work in the way you are hoping. If we take your langmodcontroller route and change it to this:

$router->addRoute('langmodcontroller',new Zend_Controller_Router_Route(
    '/:lang/:module/:controller',
    array(
        'lang' => ':lang',
        'controller' => 'index'
        'action' => 'index' 
    )
));

现在有了控制器变量的默认值。如果我们假装这是唯一的路线,那么对 / en / blog 的请求现在将与此匹配,并将请求参数设置为lang = en,module =博客,控制器=索引,操作=索引。 / en / blog / index / foo 也会匹配此路由,并为您提供模块=博客,控制器=索引,操作= foo。但是请注意,即使controller = index,您仍然需要在URL中使用它。因此第二个限制是,只要在URL之后有不是默认值的内容,就始终需要URL中的变量(即使将其设置为默认值)。

there's now a default value for the controller variable. If we pretend for a second that this was the only route, a request for /en/blog would now get matched by this and set the request params to lang = en, module = blog, controller = index, action = index. /en/blog/index/foo would also match this route, and would give you module = blog, controller = index, action = foo. But note that even though controller = index you still need that in the URL. So limitation number two is that you always need the variable in the URL (even if it is set to your default) as long as you have something after it that isn't the default.

考虑到这些限制,我建议您使用这样的东西(按此顺序定义):

With these limitations in mind I'd suggest you go with something like this (defined in this order):

/: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)

这将为您提供如下网址:

This would give you URLs like this:

/en
/en/controller
/en/controller/action
/en/action
/en/controller/param
/en/admin/controller
/en/admin/controller/action

这就是您所追求的。

ZF中的路由功能非常强大,您只需要了解其怪癖即可。

The routing in ZF is very powerful, you just need to know its quirks.

这篇关于Zend路由问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆