Zend Framework:如何映射完全动态的路由

时间:2011-01-07 13:44:37

标签: zend-framework routes

这个问题的标题很难提出,反正可能不是最好的。

我有一个包含地区,类别和供应商的网站,显而易见的解决方案是使用默认路径

"/:module/:controller/:action"

这样我的网址就会像这样

"/region/midlands/category/fashion"
"/region/midlands/supplier/ted-baker"

我想要实现的是这样的URL格式,但是,这需要涉及数据库查询以检查是否存在midlandsfashionted-baker

"/midlands/fashion"
"/midlands/ted-baker"

我原来的解决方案是使用类似的东西

"/region/midlands/fashion"

将路线定义为

routes.category.route = "/region/:region/:category"
routes.category.defaults.controller = category
routes.category.defaults.action = index
routes.category.defaults.module = default
routes.category.defaults.category = false
routes.category.defaults.region = false

routes.supplier.route = "/supplier/:supplier"
routes.supplier.defaults.controller = supplier
routes.supplier.defaults.action = index
routes.supplier.defaults.module = default
routes.supplier.defaults.supplier = false

但这意味着使用regionsupplier为所有内容添加前缀。我几乎需要用插件完全劫持请求?

实现这一目标的最佳方式是什么?

感谢您的帮助。

修改

@St.Woland,问题是我想要这条路线

/:region/:supplier

使用此网址

/midlands/ted-baker

但该路由有效地覆盖了默认路由器

2 个答案:

答案 0 :(得分:2)

最好的方法是在Bootstrap类中添加一个方法,如下所示:

<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initMyRoutes()
    {
        // First, initialize Database resource
        $this->bootstrap('db');
        // Second, initialize Router resource
        $this->bootstrap('router');

        // Finally, instantiate your database table with routes
        $m_routes = new Model_Routes() ;

        // Now get the Router
        $router = $this->getResource('router');

        // ... and add all routes from the database
        foreach( $m_routes->fetchAll() as $route ) {
            $router->addRoute( $route->name, new Zend_Controller_Router_Route( $route->path, $route->toArray() ) ) ;
        }
    }
}

然后在application.ini

[production]
bootstrap.path = APPLICATION_PATH/Bootstrap.php
bootstrap.class = Bootstrap

这将使用来自数据库的路由初始化路由器。

您应该记住,在每次请求时对数据库进行排队都不高效,因此请务必使用缓存。

答案 1 :(得分:0)

我最后使用ErrorController来做到这一点。我抓住了有控制器或没有路线的例外,然后采取相应行动。

对于特定路径的几个数据库表进行了调用,而不是像在St.Woland的解决方案中那样获取所有路径。结果缓存了标签,这有助于大量工作,这将删除所有数据库查询以查找路径

public function errorAction()
{
    $errors = $this->_getParam('error_handler');

    switch ($errors->type) 
    {
        case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
        case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            //Code for locating routes in Db goes here
    }
}