ZF1:数据库中的路由

时间:2014-02-17 14:15:30

标签: php zend-framework zend-controller-router zend-framework-routing zend-controller-plugin

我正在为ZendFramework应用程序构建一个简单的CMS模块。

目前我在.ini文件中拥有所有路由,是否可以使其成为数据库驱动的。或者,如果可以为数据库构建回退方法,请检查.ini文件中是否存在该路由。

更新 - 解决方案

希望这会对某人有所帮助 - 请注意我有自定义的My_Db_table和My_Db_Row,我还没有在这里发布。所以 - > fetchAllActive()可能需要更改为 - > fetchAll();并且行对象上的getter可能/可能不起作用,不记得它们是否是自定义的 - 你会弄明白的; - )

但是,如果没有其他路由适用,路由器基本上会检查数据库,即来自.ini文件。我没有检查它是否适用于所有路由类型,但它适用于默认路由类型。我使用数据库路由将URL指向一个pageController,其中包含在route_defaults单元格中存储为JSON字符串的其他参数,例如pageId。但是你基本上可以将它用于所有类型的路线。

在bootstrap中

function _initApplication ()
{
    // Something taken out for simplicity

    $this->bootstrap('frontcontroller');
    $front = $this->getResource('frontcontroller');

    $router = new My_Controller_Router_Rewrite();
    $front->setRouter($router);

    // Something taken out for simplicity        
}

我/控制器/路由器/ Rewrite.php

<?php

class My_Controller_Router_Rewrite extends Zend_Controller_Router_Rewrite
{


    /**
     * Retrieve a named route
     *
     * @param string $name Name of the route
     * @throws Zend_Controller_Router_Exception
     * @return Zend_Controller_Router_Route_Interface Route object
     */
    public function getRoute($name)
    {
        if (!isset($this->_routes[$name])) {
            /* BEGIN - DB routes */
            $routes = new Routes();
            $route = $routes->getNamedRoute($name);
            if($route instanceof Zend_Controller_Router_Route_Abstract) {
                $this->addRoute($name, $route); 
            }
            /* END - DB routes */
            if (!isset($this->_routes[$name])) {
                require_once 'Zend/Controller/Router/Exception.php';
                throw new Zend_Controller_Router_Exception("Route $name is not defined");
            }
        }

        return $this->_routes[$name];
    }


    /**
     * Find a matching route to the current PATH_INFO and inject
     * returning values to the Request object.
     *
     * @throws Zend_Controller_Router_Exception
     * @return Zend_Controller_Request_Abstract Request object
     */
    public function route(Zend_Controller_Request_Abstract $request)
    {
        if (!$request instanceof Zend_Controller_Request_Http) {
            require_once 'Zend/Controller/Router/Exception.php';
            throw new Zend_Controller_Router_Exception('Zend_Controller_Router_Rewrite requires a Zend_Controller_Request_Http-based request object');
        }

        if ($this->_useDefaultRoutes) {
            $this->addDefaultRoutes();
        }

        // Find the matching route
        $routeMatched = false;

        foreach (array_reverse($this->_routes, true) as $name => $route) {
            // TODO: Should be an interface method. Hack for 1.0 BC
            if (method_exists($route, 'isAbstract') && $route->isAbstract()) {
                continue;
            }

            // TODO: Should be an interface method. Hack for 1.0 BC
            if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) {
                $match = $request->getPathInfo();
            } else {
                $match = $request;
            }

            if ($params = $route->match($match)) {
                $this->_setRequestParams($request, $params);
                $this->_currentRoute = $name;
                $routeMatched        = true;
                break;
            }
        }

        /* BEGIN - DB routes */
        $front = Zend_Controller_Front::getInstance();

        if (!$routeMatched || ($routeMatched && !Zend_Controller_Front::getInstance()->getDispatcher()->isDispatchable($request))) {
            $routes = new Routes();
            $dbRoutes = $routes->getRouterRoutes();

            foreach ($dbRoutes as $name => $route) {
                // TODO: Should be an interface method. Hack for 1.0 BC
                if (method_exists($route, 'isAbstract') && $route->isAbstract()) {
                    continue;
                }

                // TODO: Should be an interface method. Hack for 1.0 BC
                if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) {
                    $match = $request->getPathInfo();
                } else {
                    $match = $request;
                }

                if ($params = $route->match($match)) {
                    $this->_setRequestParams($request, $params);
                    $this->_currentRoute = $name;
                    $routeMatched        = true;
                    break;
                }
            }
        }
        /* END - DB routes */

        if(!$routeMatched) {
            require_once 'Zend/Controller/Router/Exception.php';
            throw new Zend_Controller_Router_Exception('No route matched the request', 404);
        }

        if($this->_useCurrentParamsAsGlobal) {
            $params = $request->getParams();
            foreach($params as $param => $value) {
                $this->setGlobalParam($param, $value);
            }
        }

        return $request;

    }

}

路由Db_Table模型

<?php

class Routes extends My_Db_Table
{
    protected $_name = 'routes';
    protected $_rowClass = 'Route';

    public static $primaryColumn = 'route_id';
    public static $statusColumn = 'route_status';
    public static $nameColumn = 'route_name';
    public static $typeColumn = 'route_type';
    public static $urlColumn = 'route_url';
    public static $moduleColumn = 'route_module';
    public static $controllerColumnn = 'route_controller';
    public static $actionColumnn = 'route_action';
    public static $defaultsColumnn = 'route_defaults';
    public static $reqsColumnn = 'route_reqs';
    public static $createdColumnn = 'route_created';

    public function getRouterRoutes() {
        $routes = array();
        $rowset = $this->fetchAllActive();
        foreach($rowset as $row) {
            $routes[$row->getName()] = $row->getRouteObject();
        }
        return $routes;     
    }

    public function getNamedRoute($name) {
        $select = $this->select()
                        ->where(self::$statusColumn . ' = ?', 1)
                        ->where(self::$nameColumn . ' = ?', $name);
        $rowset = $this->fetchAll($select);
        foreach($rowset as $row) {
            return $row->getRouteObject();
        }
    }
}

路线 - Db_Table_row

<?php

class Route extends My_Db_Table_Row_Observable
{

    public function getType() {
        if(empty($this->{Routes::$typeColumn})) {
            return "Zend_Controller_Router_Route";
        } else {
            return $this->{Routes::$typeColumn};
        }
    }

    public function getDefaults() {
        $defaults = $this->{Routes::$defaultsColumnn};
        if($defaults) {
            $defaults = Zend_Json::decode($defaults);
        } else {
            $defaults = array();
        }

        $defaults['module'] = $this->getModule();
        $defaults['controller'] = $this->getController();
        $defaults['action'] = $this->getAction();

        return $defaults;
    }

    public function getReqs() {
        $reqs = $this->{Routes::$reqsColumnn};
        if($reqs) {
            $reqs = Zend_Json::decode($reqs);
        } else {
            $reqs = array();
        }
        return $reqs;
    }

    public function getModule() {
        if(empty($this->{Routes::$moduleColumn})) {
            return "default";
        } else {
            return $this->{Routes::$moduleColumn};
        }
    }
    public function getController() {
        if(empty($this->{Routes::$controllerColumnn})) {
            return "default";
        } else {
            return $this->{Routes::$controllerColumnn};
        }
    }
    public function getAction() {
        if(empty($this->{Routes::$actionColumnn})) {
            return "default";
        } else {
            return $this->{Routes::$actionColumnn};
        }
    }
    public function getRouteObject() {
        $class = $this->getType();
        $defaults = $this->getDefaults();
        $reqs = $this->getReqs();
        $route = new $class($this->getUrl(), $defaults, $reqs);
        return $route;
    }
}

路由表的SQL架构

CREATE TABLE IF NOT EXISTS `routes` (
  `route_id` smallint(1) unsigned NOT NULL AUTO_INCREMENT,
  `route_status` tinyint(1) unsigned NOT NULL,
  `route_name` varchar(16) NOT NULL,
  `route_type` varchar(255) NOT NULL,
  `route_url` varchar(255) NOT NULL,
  `route_module` varchar(32) NOT NULL,
  `route_controller` varchar(32) NOT NULL,
  `route_action` varchar(32) NOT NULL,
  `route_defaults` varchar(255) NOT NULL,
  `route_reqs` varchar(255) NOT NULL,
  `route_created` datetime NOT NULL,
  PRIMARY KEY (`route_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;

1 个答案:

答案 0 :(得分:0)

我可以想到三种方法。

首先是我在ZF1中成功使用的。 Here's the code用于路由本身。这个想法很简单:设置一个“别名”路由(在我的例子中,它只是使用“.html”后缀来区分它与其他URL)。如果找到了路由,您可以从DB获取别名,然后将请求从目标控制器+操作转发到DB(like here)中定义的内容。我的代码并不漂亮,但它确实有用。

第二:编写自己的路由器。您可以扩展路由器类,只需在那里添加自己的路由解析规则:从数据库获取数据,如果别名在数据库中,则返回true(并设置params)。

第三步:抓取别名表并将所有内容存储在.ini文件(或您可能使用的任何缓存)中。这与您已经实现的内容没有太大的不同,您需要做的就是自动化别名抓取。