1

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

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

更新 - 解决方案

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

但是如果没有其他路由适用,即从 .ini 文件中,路由器基本上会检查 DB。我没有检查这是否适用于所有路由类型,但它适用于默认路由类型。我使用 DB 路由将 url 指向 pageController,并在 route_defaults 单元格中将 pageId 等附加参数存储为 JSON 字符串。但是您基本上可以将其用于所有类型的路线。

在引导程序中

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 ;
4

1 回答 1

0

我能想到三种方法。

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

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

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

于 2014-02-17T14:30:56.713 回答