1

Я создаю простой модуль 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 ; 
+0

Возможно, эта статья может вам помочь: http://richard.parnaby-king.co.uk/2013/04/zend-framework-routing-solutions/ – Flixer

ответ

0

Есть три подхода, которые я могу думать.

Во-первых, это то, что я успешно использовал в ZF1. Here's the code для самой маршрутизации. Идея проста: установите «псевдоним» маршрутизации (которая в моем случае просто использовала суффикс «.html», чтобы отличить его от других URL-адресов). Если найдена маршрутизация, вы можете получить псевдоним из БД, а затем перенаправить запрос от целевого контроллера + на то, что определено в БД (like here). Мой код не очень хорош, но он работает.

Во-вторых: напишите свой собственный маршрутизатор. Вы можете расширить класс маршрутизатора и просто добавить свои собственные правила разрешения маршрута: получить данные из БД, вернуть true (и установить параметры), если псевдоним находится в базе данных.

В-третьих: очистите таблицу псевдонимов и сохраните все в файле .ini (или любом кеше, который вы могли бы использовать). Это не сильно отличается от того, что вы уже реализовали, и все, что вам нужно сделать, - автоматизировать скрежет псевдонима.

+0

Я закончил расширение Zend_Controler_Router_Rewrite - И в функции route() сделайте проверку против БД, если запрос не будет сопоставлен повторно на пути, способном к отправке, из загруженного маршрута.Только другое изменение необходимо было указать приложение в bootstrap, чтобы использовать мой класс My_Controller_Router_Rewrite :-) – Phliplip

+0

Я считаю, что это тоже «правильный» :) – mingos

+0

Я добавил свое решение в OP – Phliplip