php教程 PHP开发 Zend_Controller_Router 함수로 자세히 설명된 Zend Framework 튜토리얼 로드

Zend_Controller_Router 함수로 자세히 설명된 Zend Framework 튜토리얼 로드

Jan 03, 2017 pm 01:10 PM

이 기사의 예에서는 Zend Framework 튜토리얼 라우팅 기능 Zend_Controller_Router의 사용법을 설명합니다. 참고할 수 있도록 모든 사람과 공유하세요. 자세한 내용은 다음과 같습니다.

Zend Framework의 라우팅은 라우팅과 생성 라우팅이라는 두 가지 주요 기능을 제공합니다.

Zend_Controller_Router의 Route 클래스와 해당 Route 디렉터리의 클래스는 일반적인 라우팅 작업을 정의합니다.

Zend_Controller_Router_Interface 인터페이스, Zend_Controller_Router_Abstract 및 Zend_Controller_Router_Rewrite 클래스는 기본 라우팅, 경로 생성 및 삭제 기능을 완성합니다.

└── 라우터
├── Abstract.php
├── Exception.php
├── Interface.php
├── Rewrite.php
├ ── 경로
    │   ├── Abstract.php
    │   ├── Chain.php
    │   ├── Hostname.php
    │   ├── Interface.php
    │   ├── Module.php
│ ├ ─ ─ regex.php
│ └ ─ ─ 🎜> └ ─ Route.php

Zend_Controller_Router Route 기능 구현

Zend_Controller _Interface

<?php
interface Zend_Controller_Router_Interface
{
  /**
   * Processes a request and sets its controller and action. If
   * no route was possible, an exception is thrown.
   *
   * @param Zend_Controller_Request_Abstract
   * @throws Zend_Controller_Router_Exception
   * @return Zend_Controller_Request_Abstract|boolean
   */
  public function route(Zend_Controller_Request_Abstract $dispatcher);
  /**
   * Generates a URL path that can be used in URL creation, redirection, etc.
   *
   * May be passed user params to override ones from URI, Request or even defaults.
   * If passed parameter has a value of null, it&#39;s URL variable will be reset to
   * default.
   *
   * If null is passed as a route name assemble will use the current Route or &#39;default&#39;
   * if current is not yet set.
   *
   * Reset is used to signal that all parameters should be reset to it&#39;s defaults.
   * Ignoring all URL specified values. User specified params still get precedence.
   *
   * Encode tells to url encode resulting path parts.
   *
   * @param array $userParams Options passed by a user used to override parameters
   * @param mixed $name The name of a Route to use
   * @param bool $reset Whether to reset to the route defaults ignoring URL params
   * @param bool $encode Tells to encode URL parts on output
   * @throws Zend_Controller_Router_Exception
   * @return string Resulting URL path
   */
  public function assemble($userParams, $name = null, $reset = false, $encode = true);
  /**
   * Retrieve Front Controller
   *
   * @return Zend_Controller_Front
   */
  public function getFrontController();
  /**
   * Set Front Controller
   *
   * @param Zend_Controller_Front $controller
   * @return Zend_Controller_Router_Interface
   */
  public function setFrontController(Zend_Controller_Front $controller);
  /**
   * Add or modify a parameter with which to instantiate any helper objects
   *
   * @param string $name
   * @param mixed $param
   * @return Zend_Controller_Router_Interface
   */
  public function setParam($name, $value);
  /**
   * Set an array of a parameters to pass to helper object constructors
   *
   * @param array $params
   * @return Zend_Controller_Router_Interface
   */
  public function setParams(array $params);
  /**
   * Retrieve a single parameter from the controller parameter stack
   *
   * @param string $name
   * @return mixed
   */
  public function getParam($name);
  /**
   * Retrieve the parameters to pass to helper object constructors
   *
   * @return array
   */
  public function getParams();
  /**
   * Clear the controller parameter stack
   *
   * By default, clears all parameters. If a parameter name is given, clears
   * only that parameter; if an array of parameter names is provided, clears
   * each.
   *
   * @param null|string|array single key or array of keys for params to clear
   * @return Zend_Controller_Router_Interface
   */
  public function clearParams($name = null);
}
로그인 후 복사

Zend_Controller_Router_Abstract

<?php
/** Zend_Controller_Router_Interface */
require_once &#39;Zend/Controller/Router/Interface.php&#39;;
abstract class Zend_Controller_Router_Abstract implements Zend_Controller_Router_Interface
{
  /**
   * URI delimiter
   */
  const URI_DELIMITER = &#39;/&#39;;
  /**
   * Front controller instance
   * @var Zend_Controller_Front
   */
  protected $_frontController;
  /**
   * Array of invocation parameters to use when instantiating action
   * controllers
   * @var array
   */
  protected $_invokeParams = array();
  /**
   * Constructor
   *
   * @param array $params
   * @return void
   */
  public function __construct(array $params = array())
  {
    $this->setParams($params);
  }
  /**
   * Add or modify a parameter to use when instantiating an action controller
   *
   * @param string $name
   * @param mixed $value
   * @return Zend_Controller_Router
   */
  public function setParam($name, $value)
  {
    $name = (string) $name;
    $this->_invokeParams[$name] = $value;
    return $this;
  }
  /**
   * Set parameters to pass to action controller constructors
   *
   * @param array $params
   * @return Zend_Controller_Router
   */
  public function setParams(array $params)
  {
    $this->_invokeParams = array_merge($this->_invokeParams, $params);
    return $this;
  }
  /**
   * Retrieve a single parameter from the controller parameter stack
   *
   * @param string $name
   * @return mixed
   */
  public function getParam($name)
  {
    if(isset($this->_invokeParams[$name])) {
      return $this->_invokeParams[$name];
    }
    return null;
  }
  /**
   * Retrieve action controller instantiation parameters
   *
   * @return array
   */
  public function getParams()
  {
    return $this->_invokeParams;
  }
  /**
   * Clear the controller parameter stack
   *
   * By default, clears all parameters. If a parameter name is given, clears
   * only that parameter; if an array of parameter names is provided, clears
   * each.
   *
   * @param null|string|array single key or array of keys for params to clear
   * @return Zend_Controller_Router
   */
  public function clearParams($name = null)
  {
    if (null === $name) {
      $this->_invokeParams = array();
    } elseif (is_string($name) && isset($this->_invokeParams[$name])) {
      unset($this->_invokeParams[$name]);
    } elseif (is_array($name)) {
      foreach ($name as $key) {
        if (is_string($key) && isset($this->_invokeParams[$key])) {
          unset($this->_invokeParams[$key]);
        }
      }
    }
    return $this;
  }
  /**
   * Retrieve Front Controller
   *
   * @return Zend_Controller_Front
   */
  public function getFrontController()
  {
    // Used cache version if found
    if (null !== $this->_frontController) {
      return $this->_frontController;
    }
    require_once &#39;Zend/Controller/Front.php&#39;;
    $this->_frontController = Zend_Controller_Front::getInstance();
    return $this->_frontController;
  }
  /**
   * Set Front Controller
   *
   * @param Zend_Controller_Front $controller
   * @return Zend_Controller_Router_Interface
   */
  public function setFrontController(Zend_Controller_Front $controller)
  {
    $this->_frontController = $controller;
    return $this;
  }
}
로그인 후 복사

Zend_Controller_Router_Rewrite

<?php
/** Zend_Controller_Router_Abstract */
require_once &#39;Zend/Controller/Router/Abstract.php&#39;;
/** Zend_Controller_Router_Route */
require_once &#39;Zend/Controller/Router/Route.php&#39;;
class Zend_Controller_Router_Rewrite extends Zend_Controller_Router_Abstract
{
  /**
   * Whether or not to use default routes
   *
   * @var boolean
   */
  protected $_useDefaultRoutes = true;
  /**
   * Array of routes to match against
   *
   * @var array
   */
  protected $_routes = array();
  /**
   * Currently matched route
   *
   * @var Zend_Controller_Router_Route_Interface
   */
  protected $_currentRoute = null;
  /**
   * Global parameters given to all routes
   *
   * @var array
   */
  protected $_globalParams = array();
  /**
   * Separator to use with chain names
   *
   * @var string
   */
  protected $_chainNameSeparator = &#39;-&#39;;
  /**
   * Determines if request parameters should be used as global parameters
   * inside this router.
   *
   * @var boolean
   */
  protected $_useCurrentParamsAsGlobal = false;
  /**
   * Add default routes which are used to mimic basic router behaviour
   *
   * @return Zend_Controller_Router_Rewrite
   */
  public function addDefaultRoutes()
  {
    if (!$this->hasRoute(&#39;default&#39;)) {
      $dispatcher = $this->getFrontController()->getDispatcher();
      $request = $this->getFrontController()->getRequest();
      require_once &#39;Zend/Controller/Router/Route/Module.php&#39;;
      $compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request);
      $this->_routes = array(&#39;default&#39; => $compat) + $this->_routes;
    }
    return $this;
  }
  /**
   * Add route to the route chain
   *
   * If route contains method setRequest(), it is initialized with a request object
   *
   * @param string                 $name    Name of the route
   * @param Zend_Controller_Router_Route_Interface $route   Instance of the route
   * @return Zend_Controller_Router_Rewrite
   */
  public function addRoute($name, Zend_Controller_Router_Route_Interface $route)
  {
    if (method_exists($route, &#39;setRequest&#39;)) {
      $route->setRequest($this->getFrontController()->getRequest());
    }
    $this->_routes[$name] = $route;
    return $this;
  }
  /**
   * Add routes to the route chain
   *
   * @param array $routes Array of routes with names as keys and routes as values
   * @return Zend_Controller_Router_Rewrite
   */
  public function addRoutes($routes) {
    foreach ($routes as $name => $route) {
      $this->addRoute($name, $route);
    }
    return $this;
  }
  /**
   * Create routes out of Zend_Config configuration
   *
   * Example INI:
   * routes.archive.route = "archive/:year/*"
   * routes.archive.defaults.controller = archive
   * routes.archive.defaults.action = show
   * routes.archive.defaults.year = 2000
   * routes.archive.reqs.year = "\d+"
   *
   * routes.news.type = "Zend_Controller_Router_Route_Static"
   * routes.news.route = "news"
   * routes.news.defaults.controller = "news"
   * routes.news.defaults.action = "list"
   *
   * And finally after you have created a Zend_Config with above ini:
   * $router = new Zend_Controller_Router_Rewrite();
   * $router->addConfig($config, &#39;routes&#39;);
   *
   * @param Zend_Config $config Configuration object
   * @param string   $section Name of the config section containing route&#39;s definitions
   * @throws Zend_Controller_Router_Exception
   * @return Zend_Controller_Router_Rewrite
   */
  public function addConfig(Zend_Config $config, $section = null)
  {
    if ($section !== null) {
      if ($config->{$section} === null) {
        require_once &#39;Zend/Controller/Router/Exception.php&#39;;
        throw new Zend_Controller_Router_Exception("No route configuration in section &#39;{$section}&#39;");
      }
      $config = $config->{$section};
    }
    foreach ($config as $name => $info) {
      $route = $this->_getRouteFromConfig($info);
      if ($route instanceof Zend_Controller_Router_Route_Chain) {
        if (!isset($info->chain)) {
          require_once &#39;Zend/Controller/Router/Exception.php&#39;;
          throw new Zend_Controller_Router_Exception("No chain defined");
        }
        if ($info->chain instanceof Zend_Config) {
          $childRouteNames = $info->chain;
        } else {
          $childRouteNames = explode(&#39;,&#39;, $info->chain);
        }
        foreach ($childRouteNames as $childRouteName) {
          $childRoute = $this->getRoute(trim($childRouteName));
          $route->chain($childRoute);
        }
        $this->addRoute($name, $route);
      } elseif (isset($info->chains) && $info->chains instanceof Zend_Config) {
        $this->_addChainRoutesFromConfig($name, $route, $info->chains);
      } else {
        $this->addRoute($name, $route);
      }
    }
    return $this;
  }
  /**
   * Get a route frm a config instance
   *
   * @param Zend_Config $info
   * @return Zend_Controller_Router_Route_Interface
   */
  protected function _getRouteFromConfig(Zend_Config $info)
  {
    $class = (isset($info->type)) ? $info->type : &#39;Zend_Controller_Router_Route&#39;;
    if (!class_exists($class)) {
      require_once &#39;Zend/Loader.php&#39;;
      Zend_Loader::loadClass($class);
    }
    $route = call_user_func(array($class, &#39;getInstance&#39;), $info);
    if (isset($info->abstract) && $info->abstract && method_exists($route, &#39;isAbstract&#39;)) {
      $route->isAbstract(true);
    }
    return $route;
  }
  /**
   * Add chain routes from a config route
   *
   * @param string                 $name
   * @param Zend_Controller_Router_Route_Interface $route
   * @param Zend_Config              $childRoutesInfo
   * @return void
   */
  protected function _addChainRoutesFromConfig($name,
                         Zend_Controller_Router_Route_Interface $route,
                         Zend_Config $childRoutesInfo)
  {
    foreach ($childRoutesInfo as $childRouteName => $childRouteInfo) {
      if (is_string($childRouteInfo)) {
        $childRouteName = $childRouteInfo;
        $childRoute   = $this->getRoute($childRouteName);
      } else {
        $childRoute = $this->_getRouteFromConfig($childRouteInfo);
      }
      if ($route instanceof Zend_Controller_Router_Route_Chain) {
        $chainRoute = clone $route;
        $chainRoute->chain($childRoute);
      } else {
        $chainRoute = $route->chain($childRoute);
      }
      $chainName = $name . $this->_chainNameSeparator . $childRouteName;
      if (isset($childRouteInfo->chains)) {
        $this->_addChainRoutesFromConfig($chainName, $chainRoute, $childRouteInfo->chains);
      } else {
        $this->addRoute($chainName, $chainRoute);
      }
    }
  }
  /**
   * Remove a route from the route chain
   *
   * @param string $name Name of the route
   * @throws Zend_Controller_Router_Exception
   * @return Zend_Controller_Router_Rewrite
   */
  public function removeRoute($name)
  {
    if (!isset($this->_routes[$name])) {
      require_once &#39;Zend/Controller/Router/Exception.php&#39;;
      throw new Zend_Controller_Router_Exception("Route $name is not defined");
    }
    unset($this->_routes[$name]);
    return $this;
  }
  /**
   * Remove all standard default routes
   *
   * @param Zend_Controller_Router_Route_Interface Route
   * @return Zend_Controller_Router_Rewrite
   */
  public function removeDefaultRoutes()
  {
    $this->_useDefaultRoutes = false;
    return $this;
  }
  /**
   * Check if named route exists
   *
   * @param string $name Name of the route
   * @return boolean
   */
  public function hasRoute($name)
  {
    return isset($this->_routes[$name]);
  }
  /**
   * 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])) {
      require_once &#39;Zend/Controller/Router/Exception.php&#39;;
      throw new Zend_Controller_Router_Exception("Route $name is not defined");
    }
    return $this->_routes[$name];
  }
  /**
   * Retrieve a currently matched route
   *
   * @throws Zend_Controller_Router_Exception
   * @return Zend_Controller_Router_Route_Interface Route object
   */
  public function getCurrentRoute()
  {
    if (!isset($this->_currentRoute)) {
      require_once &#39;Zend/Controller/Router/Exception.php&#39;;
      throw new Zend_Controller_Router_Exception("Current route is not defined");
    }
    return $this->getRoute($this->_currentRoute);
  }
  /**
   * Retrieve a name of currently matched route
   *
   * @throws Zend_Controller_Router_Exception
   * @return Zend_Controller_Router_Route_Interface Route object
   */
  public function getCurrentRouteName()
  {
    if (!isset($this->_currentRoute)) {
      require_once &#39;Zend/Controller/Router/Exception.php&#39;;
      throw new Zend_Controller_Router_Exception("Current route is not defined");
    }
    return $this->_currentRoute;
  }
  /**
   * Retrieve an array of routes added to the route chain
   *
   * @return array All of the defined routes
   */
  public function getRoutes()
  {
    return $this->_routes;
  }
  /**
   * 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 &#39;Zend/Controller/Router/Exception.php&#39;;
      throw new Zend_Controller_Router_Exception(&#39;Zend_Controller_Router_Rewrite requires a Zend_Controller_Request_Http-based request object&#39;);
    }
    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, &#39;isAbstract&#39;) && $route->isAbstract()) {
        continue;
      }
      // TODO: Should be an interface method. Hack for 1.0 BC
      if (!method_exists($route, &#39;getVersion&#39;) || $route->getVersion() == 1) {
        $match = $request->getPathInfo();
      } else {
        $match = $request;
      }
      if ($params = $route->match($match)) {
        $this->_setRequestParams($request, $params);
        $this->_currentRoute = $name;
        $routeMatched    = true;
        break;
      }
    }
     if (!$routeMatched) {
       require_once &#39;Zend/Controller/Router/Exception.php&#39;;
       throw new Zend_Controller_Router_Exception(&#39;No route matched the request&#39;, 404);
     }
    if($this->_useCurrentParamsAsGlobal) {
      $params = $request->getParams();
      foreach($params as $param => $value) {
        $this->setGlobalParam($param, $value);
      }
    }
    return $request;
  }
  protected function _setRequestParams($request, $params)
  {
    foreach ($params as $param => $value) {
      $request->setParam($param, $value);
      if ($param === $request->getModuleKey()) {
        $request->setModuleName($value);
      }
      if ($param === $request->getControllerKey()) {
        $request->setControllerName($value);
      }
      if ($param === $request->getActionKey()) {
        $request->setActionName($value);
      }
    }
  }
  /**
   * Generates a URL path that can be used in URL creation, redirection, etc.
   *
   * @param array $userParams Options passed by a user used to override parameters
   * @param mixed $name The name of a Route to use
   * @param bool $reset Whether to reset to the route defaults ignoring URL params
   * @param bool $encode Tells to encode URL parts on output
   * @throws Zend_Controller_Router_Exception
   * @return string Resulting absolute URL path
   */
  public function assemble($userParams, $name = null, $reset = false, $encode = true)
  {
    if (!is_array($userParams)) {
      require_once &#39;Zend/Controller/Router/Exception.php&#39;;
      throw new Zend_Controller_Router_Exception(&#39;userParams must be an array&#39;);
    }
    if ($name == null) {
      try {
        $name = $this->getCurrentRouteName();
      } catch (Zend_Controller_Router_Exception $e) {
        $name = &#39;default&#39;;
      }
    }
    // Use UNION (+) in order to preserve numeric keys
    $params = $userParams + $this->_globalParams;
    $route = $this->getRoute($name);
    $url  = $route->assemble($params, $reset, $encode);
    if (!preg_match(&#39;|^[a-z]+://|&#39;, $url)) {
      $url = rtrim($this->getFrontController()->getBaseUrl(), self::URI_DELIMITER) . self::URI_DELIMITER . $url;
    }
    return $url;
  }
  /**
   * Set a global parameter
   *
   * @param string $name
   * @param mixed $value
   * @return Zend_Controller_Router_Rewrite
   */
  public function setGlobalParam($name, $value)
  {
    $this->_globalParams[$name] = $value;
    return $this;
  }
  /**
   * Set the separator to use with chain names
   *
   * @param string $separator The separator to use
   * @return Zend_Controller_Router_Rewrite
   */
  public function setChainNameSeparator($separator) {
    $this->_chainNameSeparator = $separator;
    return $this;
  }
  /**
   * Get the separator to use for chain names
   *
   * @return string
   */
  public function getChainNameSeparator() {
    return $this->_chainNameSeparator;
  }
  /**
   * Determines/returns whether to use the request parameters as global parameters.
   *
   * @param boolean|null $use
   *      Null/unset when you want to retrieve the current state.
   *      True when request parameters should be global, false otherwise
   * @return boolean|Zend_Controller_Router_Rewrite
   *       Returns a boolean if first param isn&#39;t set, returns an
   *       instance of Zend_Controller_Router_Rewrite otherwise.
   *
   */
  public function useRequestParametersAsGlobal($use = null) {
    if($use === null) {
      return $this->_useCurrentParamsAsGlobal;
    }
    $this->_useCurrentParamsAsGlobal = (bool) $use;
    return $this;
  }
}
로그인 후 복사

경로 추가 방법

공용 함수 addRoute($name, Zend_Controller_Router_Route_Interface $route)

공용 함수 addRoutes($routes)

$router = $ctrl->getRouter(); // returns a rewrite router by default
$router->addRoute(&#39;user&#39;,
         new Zend_Controller_Router_Route(&#39;user/:username&#39;));
로그인 후 복사

addRoute의 첫 번째 매개변수는 경로 이름입니다. 두 번째 매개변수는 경로 자체입니다. 경로 이름의 가장 일반적인 사용은 Zend_View_Url 도우미 메서드인

"<?= $this->url(array(&#39;username&#39; => &#39;martel&#39;), &#39;user&#39;) ?>">Martel</a>
로그인 후 복사

을 통해 사용되며 결과적으로 href: user/martel이 됩니다.

라우팅은 현재 요청에 대해 제공된 모든 경로와 일치하는 URI 정의를 반복하는 간단한 프로세스입니다. 긍정적인 일치 항목이 발견되면 경로 인스턴스에서 변수 값이 반환되고 향후 디스패처 및 사용자 생성 컨트롤러에서 사용할 수 있도록 Zend_Controller_Request 개체에 주입됩니다. 부정적으로 일치하는 경우 체인의 다음 경로가 확인됩니다.

참고: 역순으로 일치

경로를 역순으로 일치시키면 가장 일반적인 경로가 먼저 정의됩니다.

참고: 반환된 값

경로에서 반환된 값은 URL 매개변수 또는 정의에 사용된 기본값에서 옵니다. 이러한 변수는 나중에 Zend_Controller_Request::getParam() 또는 Zend_Controller_Action::_getParam() 메서드를 통해 액세스할 수 있습니다.

경로에 '모듈', '컨트롤러', '액션'이라는 세 가지 특수 변수를 사용할 수 있습니다. 이러한 특수 변수는 Zend_Controller_Dispatcher에서 컨트롤러와 작업을 찾아 전달하는 데 사용됩니다.

참고: 특수 변수

setControllerKey 및 setActionKey 메소드를 통해 기본값을 변경하도록 선택한 경우 이러한 특수 변수의 이름이 다를 수 있습니다.

기본 경로

Zend_Controller_Router_Rewrite는 컨트롤러/액션 형식의 URI와 일치하는 기본 경로로 사전 구성됩니다. 또한 모듈 이름을 첫 번째 경로 매개변수로 지정하여 모듈/컨트롤러/작업 형식의 URI를 허용할 수 있습니다. 마지막으로 URI(controller/action/var1/value1/var2/value2)에 추가된 모든 추가 매개변수를 일치시키는 것이 기본값입니다.

경로 일치 방법에 대한 몇 가지 예:

// Assuming the following:
$ctrl->setControllerDirectory(
  array(
    &#39;default&#39; => &#39;/path/to/default/controllers&#39;,
    &#39;news&#39;  => &#39;/path/to/news/controllers&#39;,
    &#39;blog&#39;  => &#39;/path/to/blog/controllers&#39;
  )
);
Module only:
http://example/news
  module == news
Invalid module maps to controller name:
http://example/foo
  controller == foo
Module + controller:
http://example/blog/archive
  module   == blog
  controller == archive
Module + controller + action:
http://example/blog/archive/list
  module   == blog
  controller == archive
  action   == list
Module + controller + action + params:
http://example/blog/archive/list/sort/alpha/date/desc
  module   == blog
  controller == archive
  action   == list
  sort    == alpha
  date    == desc
로그인 후 복사

기본 경로는 RewriteRouter에 '(index)라는 이름으로 저장됩니다. default' 단순 Zend_Controller_Router_Route_Module 개체입니다. 이는 대략 다음과 같이 생성됩니다.

$compat = new Zend_Controller_Router_Route_Module(array(),
                         $dispatcher,
                         $request);
$this->addRoute(&#39;default&#39;, $compat);
로그인 후 복사

라우팅 계획에서 이 특정 기본 경로를 원하지 않으면 다음과 같이 다시 작성할 수 있습니다. 자신만의 '기본' 경로(예: 'default'라는 이름으로 저장) 또는 RemoveDefaultRoutes()를 사용하여 완전히 지우세요:

// Remove any default routes
$router->removeDefaultRoutes();
로그인 후 복사

In 라우팅의 유연성을 높이고 새로운 라우팅 유형의 사용자 정의를 용이하게 하기 위해 Zend_Controller_Router는 Zend_Controller_Router_Route_Interface 인터페이스를 정의하고 해당 클래스 메소드를 구현하면 라우팅 유형을 정의할 수 있어 개발이 용이해집니다.

Zend_Controller_Router의 경로 유형

Zend_Controller_Router는 기본적으로 다음과 같은 경로 유형을 제공합니다.

Zend_Controller_Router_Route

Zend_Controller_Router_Route_Static
Zend_Controller_Router_Ro ute_Reg ex
Zend_Controller_Router_Route_Hostname
Zend_Controller_Router_Route_Module
Zend_Controller_Router_Route_Chain
Zend_Controller_Router_Route

Zend_Controller_Router_Route는 표준 프레임워크 경로입니다. 이는 사용 편의성과 유연한 경로 정의를 결합합니다. 각 경로에는 기본 URL 매핑(정적 및 동적 부분(변수))이 포함되어 있으며 기본적으로 또는 다른 요구 사항에 따라 초기화될 수 있습니다.

让我们想象一下我们假设的应用程序将需要一些广域内容作者的信息页面。我们想能够把浏览器指向http://domain.com/author/martel去看一个叫"martel"的信息。有这样功能的路由看起来是这样的:

$route = new Zend_Controller_Router_Route(
  &#39;author/:username&#39;,
  array(
    &#39;controller&#39; => &#39;profile&#39;,
    &#39;action&#39;   => &#39;userinfo&#39;
  )
);
$router->addRoute(&#39;user&#39;, $route);
로그인 후 복사

在Zend_Controller_Router_Route里构造函数的第一个参数是路由的定义,它将匹配一个URL。路由定义包含静态的和动态部分,它们由正斜杠('/')符分开。静态部分只是简单的字符:author。动态部分,被叫做变量,用预设的冒号来标记变量名::username。

Note: 字符的的用法

当前的实现允许你使用任何字符(正斜杠除外)作为变量标识符,但强烈建议只使用PHP使用的变量标识符。将来的实现也许会改变这个行为,它可能会导致在你的代码里有隐藏的bugs。

当你把浏览器指向http://domain.com/author/martel这个例子的路由应该被匹配,它所有的变量将被注入到Zend_Controller_Request对象并在ProfileController可访问。由这个例子返回的变量可能会被表示为如下键和值配对的数组:

$values = array(
  &#39;username&#39;  => &#39;martel&#39;,
  &#39;controller&#39; => &#39;profile&#39;,
  &#39;action&#39;   => &#39;userinfo&#39;
);
로그인 후 복사

稍后,基于这些值,Zend_Controller_Dispatcher_Standard应该调用ProfileController类(在缺省模块中)中的userinfoAction()方法。你将依靠Zend_Controller_Action::_getParam()或者Zend_Controller_Request::getParam()方法能够访问所有的变量:

public function userinfoAction()
{
  $request = $this->getRequest();
  $username = $request->getParam(&#39;username&#39;);
  $username = $this->_getParam(&#39;username&#39;);
}
로그인 후 복사

路由定义可以包一个额外的特别字符-通配符-表示为'*'号。它被用来取得参数,和缺省模块路由类似(在URI中定义的var=>value)。下面的路由多多少少地模仿了模块路由的行为:

$route = new Zend_Controller_Router_Route(
  &#39;:module/:controller/:action/*&#39;,
  array(&#39;module&#39; => &#39;default&#39;)
);
$router->addRoute(&#39;default&#39;, $route);
로그인 후 복사

变量缺省

在路由中每个变量可以有一个缺省值,这就是Zend_Controller_Router_Route中构造函数使用的第二个变量。这个参数是一个数组,在数组中键表示变量名,值就是期望的缺省值:

$route = new Zend_Controller_Router_Route(
  &#39;archive/:year&#39;,
  array(&#39;year&#39; => 2006)
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

上述路由将匹配象http://domain.com/archive/2005和http://example.com/archive的URLs。对于后者变量year将有一个初始的缺省值为2006。

这个例子将导致注入一个year变量给请求对象。应为没有路由信息出现(没有控制器和动作参数被定义),应用程序将被派遣给缺省的控制器和动作方法(它们都在Zend_Controller_Dispatcher_Abstract被定义)。为使它更可用,你必须提供一个有效的控制器和动作作为路由的缺省值:

$route = new Zend_Controller_Router_Route(
  &#39;archive/:year&#39;,
  array(
    &#39;year&#39;    => 2006,
    &#39;controller&#39; => &#39;archive&#39;,
    &#39;action&#39;   => &#39;show&#39;
  )
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

这个路由将导致派遣给ArchiveController类的showAction()方法。

变量请求

当变量请求被设定,第三个参数可以加给Zend_Controller_Router_Route的构造函数。这些被定义为正则表达式的一部分:

$route = new Zend_Controller_Router_Route(
  &#39;archive/:year&#39;,
  array(
    &#39;year&#39;    => 2006,
    &#39;controller&#39; => &#39;archive&#39;,
    &#39;action&#39;   => &#39;show&#39;
  ),
  array(&#39;year&#39; => &#39;\d+&#39;)
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

用上述定义的路由,路由器仅当year变量包含数字数据将匹配它,例如http://domain.com/archive/2345。象http://example.com/archive/test这样的URL将不被匹配并且控制将被传递给在链中的下一个路由。

主机名路由

你也可以使用主机名做路由匹配。对简单的匹配使用静态主机名选项:

$route = new Zend_Controller_Router_Route(
  array(
    &#39;host&#39; => &#39;blog.mysite.com&#39;,
    &#39;path&#39; => &#39;archive&#39;
  ),
  array(
    &#39;module&#39;   => &#39;blog&#39;,
    &#39;controller&#39; => &#39;archive&#39;,
    &#39;action&#39;   => &#39;index&#39;
  )
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

如果你想匹配参数在主机名里,使用 regex 选项。在下面例子中,子域为动作控制器被用作用户名参数。 当组装路由时,你可以给出用户名为参数,就像你用其它路径参数一样:

$route = new Zend_Controller_Router_Route(
  array(
    &#39;host&#39; => array(
      &#39;regex&#39;  => &#39;([a-z]+).mysite.com&#39;,
      &#39;reverse&#39; => &#39;%s.mysite.com&#39;
      &#39;params&#39; => array(
        1 => &#39;username&#39;
      )
    ),
    &#39;path&#39; => &#39;&#39;
  ),
  array(
    &#39;module&#39;   => &#39;users&#39;,
    &#39;controller&#39; => &#39;profile&#39;,
    &#39;action&#39;   => &#39;index&#39;
  )
);
로그인 후 복사

$router->addRoute('profile', $route);

Zend_Controller_Router_Route_Static

设置固定不变的路由:

$route = new Zend_Controller_Router_Route_Static(
  &#39;login&#39;,
  array(&#39;controller&#39; => &#39;auth&#39;, &#39;action&#39; => &#39;login&#39;)
);
$router->addRoute(&#39;login&#39;, $route);
로그인 후 복사

上面的路由将匹配http://domain.com/login的URL,并分派到 AuthController::loginAction().

Zend_Controller_Router_Route_Regex

除了缺省的和静态的路由类型外,正则表达式路由类型也可用。这个路由比其它路由更强更灵活,只是稍微有点复杂。同时,它应该比标准路由快。

象标准路由一样,这个路由必须用路由定义和一些缺省条件来初始化。让我们创建一个archive路由作为例子,和先前定义的类似,这次只是用了Regex:

$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive/(\d+)&#39;,
  array(
    &#39;controller&#39; => &#39;archive&#39;,
    &#39;action&#39;   => &#39;show&#39;
  )
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

每个定义的regex子模式将被注入到请求对象里。同上述的例子,再成功匹配http://domain.com/archive/2006之后,结果值的数组看起来象这样:

$values = array(
  1      => &#39;2006&#39;,
  &#39;controller&#39; => &#39;archive&#39;,
  &#39;action&#39;   => &#39;show&#39;
);
로그인 후 복사

Note: 在匹配之前,开头和结尾的斜杠从路由器里的URL中去除掉了。结果,匹配http://domain.com/foo/bar/,需要foo/bar这样的regex,而不是/foo/bar。

Note: 行开头和行结尾符号(分别为'^' 和 '$')被自动预先追加到所有表达式。这样,你不需要在你的正则表达式里用它们,你应该匹配整个字符串。

Note: 这个路由类使用#符作为分隔符。这意味着你将需要避免哈希符('#')但不是正斜杠('/')在你的路由定义里。因为'#'符(名称为锚)很少被传给webserver,你将几乎不需要在你的regex里使用它。

你可以用通常的办法获得已定义的子模式的内容:

public function showAction()
{
  $request = $this->getRequest();
  $year  = $request->getParam(1); // $year = &#39;2006&#39;;
}
로그인 후 복사

Note: 注意这个键是整数(1) 而不是字符串('1')。

因为'year'的缺省没有设置,这个路由将和它的标准路由副本不是非常精确地相同。即使我们为'year'声明一个缺省并使子模式可选,也不清楚是否会在拖尾斜杠(trailing slash)上还将有问题。方案是使整个'year'部分和斜杠一起可选但只抓取数字部分:(这段比较绕口,请校对者仔细看看,谢谢 Jason Qi)

$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive(?:/(\d+))?&#39;,
  array(
    1      => &#39;2006&#39;,
    &#39;controller&#39; => &#39;archive&#39;,
    &#39;action&#39;   => &#39;show&#39;
  )
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

让我们看看你可能注意到的问题。 给参数使用基于整数的键不是容易管理的办法,今后可能会有问题。这就是为什么有第三个参数。这是个联合数组表示一个regex子模式到参数名键的映射。我们来看看一个简单的例子:

$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive/(\d+)&#39;,
  array(
    &#39;controller&#39; => &#39;archive&#39;,
    &#39;action&#39; => &#39;show&#39;
  ),
  array(
    1 => &#39;year&#39;
  )
);
$router->addRoute(&#39;archive&#39;, $route);
로그인 후 복사

这将导致下面的值被注入到请求:

$values = array(
  &#39;year&#39;    => &#39;2006&#39;,
  &#39;controller&#39; => &#39;archive&#39;,
  &#39;action&#39;   => &#39;show&#39;
);
로그인 후 복사

这个映射被任何目录来定义使它能工作于任何环境。键可以包含变量名或子模式索引:

$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive/(\d+)&#39;,
  array( ... ),
  array(1 => &#39;year&#39;)
);
// OR
$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive/(\d+)&#39;,
  array( ... ),
  array(&#39;year&#39; => 1)
);
로그인 후 복사

Note: 子模式键必须用整数表示。

注意在请求值中的数字索引不见了,代替的是一个名字变量。当然如果你愿意可以把数字和名字变量混合使用:

$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive/(\d+)/page/(\d+)&#39;,
  array( ... ),
  array(&#39;year&#39; => 1)
);
로그인 후 복사

这将导致在请求中有混合的值可用。例如:URLhttp://domain.com/archive/2006/page/10将在下列结果中:

$values = array(
  &#39;year&#39;    => &#39;2006&#39;,
  2      => 10,
  &#39;controller&#39; => &#39;archive&#39;,
  &#39;action&#39;   => &#39;show&#39;
);
로그인 후 복사

因为regex模型不容易颠倒,如果你想用URL助手或这个类中的 assemble方法,你需要准备一个颠倒的URL。这个颠倒的路径用可由sprintf()解析的字符串来表示并定义为第四个构造参数:

$route = new Zend_Controller_Router_Route_Regex(
  &#39;archive/(\d+)&#39;,
  array( ... ),
  array(&#39;year&#39; => 1),
  &#39;archive/%s&#39;
);
로그인 후 복사

所有这些都已经可能由标准路由对象完成,那么使用Regex路由的好处在哪里?首先,它允许你不受限制地描述任何类型的URL。想象一下你有一个博客并希望创建象http://domain.com/blog/archive/01-Using_the_Regex_Router.html这样的URLs,还有把解析它路径元素中的最后部分,01-Using_the_Regex_Router.html,到一个文章的ID和文章的标题/描述;这不可能由标准路由完成。用Regex路由,你可以做象下面的方案:

$route = new Zend_Controller_Router_Route_Regex(
  &#39;blog/archive/(\d+)-(.+)\.html&#39;,
  array(
    &#39;controller&#39; => &#39;blog&#39;,
    &#39;action&#39;   => &#39;view&#39;
  ),
  array(
    1 => &#39;id&#39;,
    2 => &#39;description&#39;
  ),
  &#39;blog/archive/%d-%s.html&#39;
);
$router->addRoute(&#39;blogArchive&#39;, $route);
로그인 후 복사

正如你所看到的,这个在标准路由上添加了巨大的灵活性。

通过配置文件定义路由规则

例如

[production]
routes.archive.route = "archive/:year/*"
routes.archive.defaults.controller = archive
routes.archive.defaults.action = show
routes.archive.defaults.year = 2000
routes.archive.reqs.year = "\d+"
routes.news.type = "Zend_Controller_Router_Route_Static"
routes.news.route = "news"
routes.news.defaults.controller = "news"
routes.news.defaults.action = "list"
routes.archive.type = "Zend_Controller_Router_Route_Regex"
routes.archive.route = "archive/(\d+)"
routes.archive.defaults.controller = "archive"
routes.archive.defaults.action = "show"
routes.archive.map.1 = "year"
; OR: routes.archive.map.year = 1
로그인 후 복사

上述的INI文件可以被读进Zend_Config对象:

$config = new Zend_Config_Ini(&#39;/path/to/config.ini&#39;, &#39;production&#39;);
$router = new Zend_Controller_Router_Rewrite();
$router->addConfig($config, &#39;routes&#39;);
로그인 후 복사

在上面的例子中,我们告诉路由器去使用INI文件'routes'一节给它的路由。每个在这个节下的顶级键将用来定义路由名;上述例子定义了路由'archive'和'news'。每个路由接着要求,至少,一个'route'条目和一个或更多'defaults'条目;可选地,一个或更多'reqs'('required'的简写)可能要求提供。总之,这些相对应的三个参数提供给Zend_Controller_Router_Route_Interface对象。一个选项键,'type',可用来指定路由类的类型给特殊的路由;缺省地,它使用Zend_Controller_Router_Route。在上述例子中,'news'路由被定义来使用Zend_Controller_Router_Route_Static。

自定义路由类型

标准的rewrite路由器应当最大限度提供你所需的功能;大多时候,为了通过已知的路由提供新的或修改的功能,你将只需要创建一个新的路由类型

那就是说,你可能想要用不同的路由范例。接口Zend_Controller_Router_Interface提供了需要最少的信息来创建路由器,并包含一个单个的方法。

interface Zend_Controller_Router_Interface
{
 /**
  * @param Zend_Controller_Request_Abstract $request
  * @throws Zend_Controller_Router_Exception
  * @return Zend_Controller_Request_Abstract
  */
 public function route(Zend_Controller_Request_Abstract $request);
}
로그인 후 복사

路由只发生一次:当请求第一次接收到系统。路由器的意图是基于请求的环境决定控制器、动作和可选的参数,并把它们发给请求。请求对象接着传递给派遣器。如果不可能映射一个路由到一个派遣令牌,路由器对请求对象就什么也不做。

希望本文所述对大家PHP程序设计有所帮助。

更多Zend Framework教程之路由功能Zend_Controller_Router详解相关文章请关注PHP中文网!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)