Я создаю простой модуль CMS для своего приложения ZendFramework.ZF1: Маршруты в базе данных
В настоящее время у меня есть все мои маршруты в файле .ini, возможно ли это сделать с помощью db-driven. Или если можно построить резервный метод для проверки БД, если маршрут не существует в файле .ini.
ОБНОВЛЕНИЕ - РЕШЕНИЕ
Надеется, что это поможет кто-то - Пожалуйста, обратите внимание, что у меня есть пользовательское My_Db_table и My_Db_Row, которые я не писал здесь. Итак -> fetchAllActive(), вероятно, необходимо изменить на -> fetchAll(); и геттеры на объекте строки могут/не могут работать, не могут помнить, являются ли они обычными - вы это выясните ;-)
Но маршрутизатор в основном проверяет наличие БД, если ни один из других маршрутов не применяется, т.е. из файла .ini. Я не проверял, работает ли это со всеми типами маршрутов, но работает с типом маршрута по умолчанию. Я использую маршруты БД, чтобы указывать URL-адреса на pageController с дополнительными параметрами, такими как pageId, которые хранятся в виде строки JSON в ячейке route_defaults. Но вы можете в принципе использовать это для всех видов маршрутов.
В самозагрузки
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();
}
}
}
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 схемы для таблицы маршрутов
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 ;
Возможно, эта статья может вам помочь: http://richard.parnaby-king.co.uk/2013/04/zend-framework-routing-solutions/ – Flixer