dotxxh0998
2014-02-17 14:15
浏览 52
已采纳

ZF1:数据库中的路由

I'm building a simple CMS module for my ZendFramework application.

Currently I have all my routes in a .ini file, would it be possible to make it db-driven. Or if it's possible to build a fallback method to a DB-check if the route doesn't exists in the .ini file.

UPDATE - SOLUTION

Hope this will help somebody - Please note that I have custom My_Db_table and My_Db_Row, which I haven't posted here. So ->fetchAllActive() probably needs change to ->fetchAll(); and the getters on the row object may/may-not work, can't remember if they are custom - you'll figure it out ;-)

But Router basically check against DB if none of the other routes apply, i.e. from a .ini file. I haven't checked if this works with all the route types, but it works with the default route type. I use DB routes to point urls down to a pageController with additional params like pageId stored as a JSON string in the route_defaults cell. But you can basically use this for all kind of routes.

In 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        
}

My/Controller/Router/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;

    }

}

Routes Db_Table model

<?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();
        }
    }
}

Route - 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 schema for routes table

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条回答 默认 最新

相关推荐 更多相似问题