《PHP應用:Zend Framework教程之路由功能Zend_Controller_Router詳解》要點:
本文介紹了PHP應用:Zend Framework教程之路由功能Zend_Controller_Router詳解,希望對您有用。如果有疑問,可以聯系我們。
PHP教程本文實例講述了Zend Framework教程之路由功能Zend_Controller_Router用法.分享給大家供大家參考,具體如下:
PHP教程Zend Framework的路由提供了兩個主要功能路由和創建路由.
PHP教程Zend_Controller_Router的Route類和相應Route目錄下的類定義常見的路由操作.
PHP教程接口Zend_Controller_Router_Interface,類Zend_Controller_Router_Abstract和Zend_Controller_Router_Rewrite完成了基本的路由,創建路由,刪除路由的功能.
PHP教程└── Router
??? ├── Abstract.php
??? ├── Exception.php
??? ├── Interface.php
??? ├── Rewrite.php
??? ├── Route
??? │?? ├── Abstract.php
??? │?? ├── Chain.php
??? │?? ├── Hostname.php
??? │?? ├── Interface.php
??? │?? ├── Module.php
??? │?? ├── Regex.php
??? │?? └── Static.php
??? └── Route.php
PHP教程Zend_Controller_Router路由功能的實現
PHP教程Zend_Controller_Router_Interface
PHP教程
<?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's URL variable will be reset to
* default.
*
* If null is passed as a route name assemble will use the current Route or 'default'
* if current is not yet set.
*
* Reset is used to signal that all parameters should be reset to it'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);
}
PHP教程Zend_Controller_Router_Abstract
PHP教程
<?php
/** Zend_Controller_Router_Interface */
require_once 'Zend/Controller/Router/Interface.php';
abstract class Zend_Controller_Router_Abstract implements Zend_Controller_Router_Interface
{
/**
* URI delimiter
*/
const URI_DELIMITER = '/';
/**
* 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 'Zend/Controller/Front.php';
$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;
}
}
PHP教程Zend_Controller_Router_Rewrite
PHP教程
<?php
/** Zend_Controller_Router_Abstract */
require_once 'Zend/Controller/Router/Abstract.php';
/** Zend_Controller_Router_Route */
require_once 'Zend/Controller/Router/Route.php';
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 = '-';
/**
* 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('default')) {
$dispatcher = $this->getFrontController()->getDispatcher();
$request = $this->getFrontController()->getRequest();
require_once 'Zend/Controller/Router/Route/Module.php';
$compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request);
$this->_routes = array('default' => $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, 'setRequest')) {
$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, 'routes');
*
* @param Zend_Config $config Configuration object
* @param string $section Name of the config section containing route'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 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception("No route configuration in section '{$section}'");
}
$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 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception("No chain defined");
}
if ($info->chain instanceof Zend_Config) {
$childRouteNames = $info->chain;
} else {
$childRouteNames = explode(',', $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 : 'Zend_Controller_Router_Route';
if (!class_exists($class)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($class);
}
$route = call_user_func(array($class, 'getInstance'), $info);
if (isset($info->abstract) && $info->abstract && method_exists($route, 'isAbstract')) {
$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 'Zend/Controller/Router/Exception.php';
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 'Zend/Controller/Router/Exception.php';
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 'Zend/Controller/Router/Exception.php';
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 'Zend/Controller/Router/Exception.php';
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 '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;
}
}
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;
}
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 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception('userParams must be an array');
}
if ($name == null) {
try {
$name = $this->getCurrentRouteName();
} catch (Zend_Controller_Router_Exception $e) {
$name = 'default';
}
}
// 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('|^[a-z]+://|', $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'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;
}
}
PHP教程添加路由的操作辦法
PHP教程public function addRoute($name, Zend_Controller_Router_Route_Interface $route)
public function addRoutes($routes)
PHP教程
$router = $ctrl->getRouter(); // returns a rewrite router by default
$router->addRoute('user',
new Zend_Controller_Router_Route('user/:username'));
PHP教程addRoute的第一個參數是路由名.第二個參數是路由自己.路由名最普通的用法是通過Zend_View_Url助手的辦法:
PHP教程
"<?= $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
PHP教程它將導致在 href: user/martel.
PHP教程路由是一個簡單的過程,這個過程通過所有提供的路由和匹配它的當前哀求的URI定義來迭代.當一個正匹配被發現,變量值從路由實例返回并注入到Zend_Controller_Request對象以備將來在派遣器和用戶創建的控制器中使用.如果是負匹配,在鏈中的下個路由被檢查.
PHP教程Note: 倒序匹配
PHP教程用倒序來匹配路由確保最通用的路由被首先定義.
PHP教程Note: 返回的值
PHP教程從路由返回的值來自于URL參數或用于定義的缺省值.這些變量以后可通過Zend_Controller_Request::getParam() 或 Zend_Controller_Action::_getParam() 方法來拜訪.
PHP教程有三個特殊的變量可用于你的路由-'module'、 'controller' 和 'action'.這些特殊的變量被Zend_Controller_Dispatcher用來找出控制器和動作然后派遣過去.
PHP教程Note: 特殊變量
PHP教程如果你選擇通過 setControllerKey 和 setActionKey辦法的方式來改變缺省值,這些特殊變量的名字可能會不同.
PHP教程缺省路由
PHP教程Zend_Controller_Router_Rewrite 和缺省路由一起預先配置,它將以controller/action的形式匹配URIs.另外,模塊名可以被指定作為第一個路徑參數,允許這種module/controller/action形式的URIs.最后,它也將缺省地匹配任何另外的追加到URI的參數-controller/action/var1/value1/var2/value2.
PHP教程一些路由如何匹配的例子:
PHP教程
// Assuming the following:
$ctrl->setControllerDirectory(
array(
'default' => '/path/to/default/controllers',
'news' => '/path/to/news/controllers',
'blog' => '/path/to/blog/controllers'
)
);
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
PHP教程缺省路由是存儲在RewriteRouter名(index)為'default'的簡單的Zend_Controller_Router_Route_Module對象.它被創建多多少少象下面這樣:
PHP教程
$compat = new Zend_Controller_Router_Route_Module(array(),
$dispatcher,
$request);
$this->addRoute('default', $compat);
PHP教程如果你不想這個特別的缺省路由在你的路由計劃中,你可以重寫你自己的‘缺省'路由(例如,把它存儲在'default'名下)或用removeDefaultRoutes()完全清除它:
PHP教程
// Remove any default routes
$router->removeDefaultRoutes();
PHP教程為了增加路由的靈活性,方便自定義新的路由類型,Zend_Controller_Router定義了Zend_Controller_Router_Route_Interface接口和類Zend_Controller_Router_Route_Abstract,實現相應的類辦法即可定義路由類型,為開發提供了便利.
PHP教程Zend_Controller_Router的路由類型
PHP教程Zend_Controller_Router默認提供了以下路由類型,分別為:
PHP教程Zend_Controller_Router_Route
Zend_Controller_Router_Route_Static
Zend_Controller_Router_Route_Regex
Zend_Controller_Router_Route_Hostname
Zend_Controller_Router_Route_Module
Zend_Controller_Router_Route_Chain
Zend_Controller_Router_Route
PHP教程Zend_Controller_Router_Route是標準的框架路由.它結合了靈活路由定義的易用性.每個路由包含了基本的URL映射(靜態的和動態的部分(變量))并且可以被缺省地初始化,也可以根據不同的要求初始化.
PHP教程讓我們想象一下我們假設的應用程序將需要一些廣域內容作者的信息頁面.我們想能夠把瀏覽器指向http://domain.com/author/martel去看一個叫"martel"的信息.有這樣功能的路由看起來是這樣的:
PHP教程
$route = new Zend_Controller_Router_Route(
'author/:username',
array(
'controller' => 'profile',
'action' => 'userinfo'
)
);
$router->addRoute('user', $route);
PHP教程在Zend_Controller_Router_Route里構造函數的第一個參數是路由的定義,它將匹配一個URL.路由定義包含靜態的和動態部分,它們由正斜杠('/')符分開.靜態部分只是簡單的字符:author.動態部分,被叫做變量,用預設的冒號來標記變量名::username.
PHP教程Note: 字符的的用法
PHP教程當前的實現允許你使用任何字符(正斜杠除外)作為變量標識符,但強烈建議只使用PHP使用的變量標識符.將來的實現也許會改變這個行為,它可能會導致在你的代碼里有暗藏的bugs.
PHP教程當你把瀏覽器指向http://domain.com/author/martel這個例子的路由應該被匹配,它所有的變量將被注入到Zend_Controller_Request對象并在ProfileController可拜訪.由這個例子返回的變量可能會被表示為如下鍵和值配對的數組:
PHP教程
$values = array(
'username' => 'martel',
'controller' => 'profile',
'action' => 'userinfo'
);
PHP教程稍后,基于這些值,Zend_Controller_Dispatcher_Standard應該調用ProfileController類(在缺省模塊中)中的userinfoAction()方法.你將依靠Zend_Controller_Action::_getParam()或者Zend_Controller_Request::getParam()方法能夠拜訪所有的變量:
PHP教程
public function userinfoAction()
{
$request = $this->getRequest();
$username = $request->getParam('username');
$username = $this->_getParam('username');
}
PHP教程路由定義可以包一個額外的特別字符-通配符-表示為'*'號.它被用來取得參數,和缺省模塊路由類似(在URI中定義的var=>value).下面的路由多多少少地模仿了模塊路由的行為:
PHP教程
$route = new Zend_Controller_Router_Route(
':module/:controller/:action/*',
array('module' => 'default')
);
$router->addRoute('default', $route);
PHP教程變量缺省
PHP教程在路由中每個變量可以有一個缺省值,這就是Zend_Controller_Router_Route中構造函數使用的第二個變量.這個參數是一個數組,在數組中鍵表示變量名,值就是期望的缺省值:
PHP教程
$route = new Zend_Controller_Router_Route(
'archive/:year',
array('year' => 2006)
);
$router->addRoute('archive', $route);
PHP教程上述路由將匹配象http://domain.com/archive/2005和http://example.com/archive的URLs.對于后者變量year將有一個初始的缺省值為2006.
PHP教程這個例子將導致注入一個year變量給哀求對象.應為沒有路由信息出現(沒有控制器和動作參數被定義),應用程序將被派遣給缺省的控制器和動作方法(它們都在Zend_Controller_Dispatcher_Abstract被定義).為使它更可用,你必須提供一個有效的控制器和動作作為路由的缺省值:
PHP教程
$route = new Zend_Controller_Router_Route(
'archive/:year',
array(
'year' => 2006,
'controller' => 'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
PHP教程這個路由將導致派遣給ArchiveController類的showAction()辦法.
PHP教程變量哀求
PHP教程當變量哀求被設定,第三個參數可以加給Zend_Controller_Router_Route的構造函數.這些被定義為正則表達式的一部分:
PHP教程
$route = new Zend_Controller_Router_Route(
'archive/:year',
array(
'year' => 2006,
'controller' => 'archive',
'action' => 'show'
),
array('year' => '\d+')
);
$router->addRoute('archive', $route);
PHP教程用上述定義的路由,路由器僅當year變量包含數字數據將匹配它,例如http://domain.com/archive/2345.象http://example.com/archive/test這樣的URL將不被匹配并且控制將被傳遞給在鏈中的下一個路由.
PHP教程主機名路由
PHP教程你也可以使用主機名做路由匹配.對簡單的匹配使用靜態主機名選項:
PHP教程
$route = new Zend_Controller_Router_Route(
array(
'host' => 'blog.mysite.com',
'path' => 'archive'
),
array(
'module' => 'blog',
'controller' => 'archive',
'action' => 'index'
)
);
$router->addRoute('archive', $route);
PHP教程如果你想匹配參數在主機名里,使用 regex 選項.在下面例子中,子域為動作控制器被用作用戶名參數. 當組裝路由時,你可以給出用戶名為參數,就像你用其它路徑參數一樣:
PHP教程
$route = new Zend_Controller_Router_Route(
array(
'host' => array(
'regex' => '([a-z]+).mysite.com',
'reverse' => '%s.mysite.com'
'params' => array(
1 => 'username'
)
),
'path' => ''
),
array(
'module' => 'users',
'controller' => 'profile',
'action' => 'index'
)
);
$router->addRoute('profile', $route);
PHP教程Zend_Controller_Router_Route_Static
PHP教程設置固定不變的路由:
PHP教程
$route = new Zend_Controller_Router_Route_Static(
'login',
array('controller' => 'auth', 'action' => 'login')
);
$router->addRoute('login', $route);
PHP教程上面的路由將匹配http://domain.com/login的URL,并分派到 AuthController::loginAction().
PHP教程Zend_Controller_Router_Route_Regex
PHP教程除了缺省的和靜態的路由類型外,正則表達式路由類型也可用.這個路由比其它路由更強更靈活,只是稍微有點復雜.同時,它應該比標準路由快.
PHP教程象標準路由一樣,這個路由必須用路由定義和一些缺省條件來初始化.讓我們創建一個archive路由作為例子,和先前定義的類似,這次只是用了Regex:
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array(
'controller' => 'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
PHP教程每個定義的regex子模式將被注入到哀求對象里.同上述的例子,再成功匹配http://domain.com/archive/2006之后,結果值的數組看起來象這樣:
PHP教程
$values = array(
1 => '2006',
'controller' => 'archive',
'action' => 'show'
);
PHP教程Note: 在匹配之前,開頭和結尾的斜杠從路由器里的URL中去除掉了.結果,匹配http://domain.com/foo/bar/,需要foo/bar這樣的regex,而不是/foo/bar.
PHP教程Note: 行開頭和行結尾符號(分別為'^' 和 '$')被自動預先追加到所有表達式.這樣,你不需要在你的正則表達式里用它們,你應該匹配整個字符串.
PHP教程Note: 這個路由類使用#符作為分隔符.這意味著你將需要避免哈希符('#')但不是正斜杠('/')在你的路由定義里.因為'#'符(名稱為錨)很少被傳給webserver,你將幾乎不需要在你的regex里使用它.
PHP教程你可以用通常的方法獲得已定義的子模式的內容:
PHP教程
public function showAction()
{
$request = $this->getRequest();
$year = $request->getParam(1); // $year = '2006';
}
PHP教程Note: 注意這個鍵是整數(1) 而不是字符串('1').
PHP教程因為'year'的缺省沒有設置,這個路由將和它的標準路由副本不是非常精確地相同.即使我們為'year'聲明一個缺省并使子模式可選,也不清楚是否會在拖尾斜杠(trailing slash)上還將有問題.方案是使整個'year'部分和斜杠一起可選但只抓取數字部分:(這段比較繞口,請校對者仔細看看,謝謝 Jason Qi)
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'archive(?:/(\d+))?',
array(
1 => '2006',
'controller' => 'archive',
'action' => 'show'
)
);
$router->addRoute('archive', $route);
PHP教程讓我們看看你可能注意到的問題. 給參數使用基于整數的鍵不是容易管理的方法,今后可能會有問題.這就是為什么有第三個參數.這是個聯合數組表示一個regex子模式到參數名鍵的映射.我們來看看一個簡單的例子:
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array(
'controller' => 'archive',
'action' => 'show'
),
array(
1 => 'year'
)
);
$router->addRoute('archive', $route);
PHP教程這將導致下面的值被注入到哀求:
PHP教程
$values = array(
'year' => '2006',
'controller' => 'archive',
'action' => 'show'
);
PHP教程這個映射被任何目錄來定義使它能工作于任何環境.鍵可以包含變量名或子模式索引:
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array(1 => 'year')
);
// OR
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array('year' => 1)
);
PHP教程Note: 子模式鍵必須用整數表示.
PHP教程注意在哀求值中的數字索引不見了,代替的是一個名字變量.當然如果你愿意可以把數字和名字變量混合使用:
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)/page/(\d+)',
array( ... ),
array('year' => 1)
);
PHP教程這將導致在哀求中有混合的值可用.例如:URLhttp://domain.com/archive/2006/page/10將在下列結果中:
PHP教程
$values = array(
'year' => '2006',
2 => 10,
'controller' => 'archive',
'action' => 'show'
);
PHP教程因為regex模型不容易顛倒,如果你想用URL助手或這個類中的 assemble辦法,你需要準備一個顛倒的URL.這個顛倒的路徑用可由sprintf()解析的字符串來表示并定義為第四個構造參數:
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'archive/(\d+)',
array( ... ),
array('year' => 1),
'archive/%s'
);
PHP教程所有這些都已經可能由標準路由對象完成,那么使用Regex路由的好處在哪里?首先,它允許你不受限制地描述任何類型的URL.想象一下你有一個博客并希望創建象http://domain.com/blog/archive/01-Using_the_Regex_Router.html這樣的URLs,還有把解析它路徑元素中的最后部分,01-Using_the_Regex_Router.html,到一個文章的ID和文章的標題/描述;這不可能由標準路由完成.用Regex路由,你可以做象下面的方案:
PHP教程
$route = new Zend_Controller_Router_Route_Regex(
'blog/archive/(\d+)-(.+)\.html',
array(
'controller' => 'blog',
'action' => 'view'
),
array(
1 => 'id',
2 => 'description'
),
'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);
PHP教程正如你所看到的,這個在標準路由上添加了巨大的靈活性.
PHP教程通過配置文件定義路由規則
PHP教程例如
PHP教程
[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
PHP教程上述的INI文件可以被讀進Zend_Config對象:
PHP教程
$config = new Zend_Config_Ini('/path/to/config.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router->addConfig($config, 'routes');
PHP教程在上面的例子中,我們告訴路由器去使用INI文件'routes'一節給它的路由.每個在這個節下的頂級鍵將用來定義路由名;上述例子定義了路由'archive'和'news'.每個路由接著要求,至少,一個'route'條目和一個或更多'defaults'條目;可選地,一個或更多'reqs'('required'的簡寫)可能要求提供.總之,這些相對應的三個參數提供給Zend_Controller_Router_Route_Interface對象.一個選項鍵,'type',可用來指定路由類的類型給特殊的路由;缺省地,它使用Zend_Controller_Router_Route.在上述例子中,'news'路由被定義來使用Zend_Controller_Router_Route_Static.
PHP教程自定義路由類型
PHP教程標準的rewrite路由器應當最大限度提供你所需的功能;大多時候,為了通過已知的路由提供新的或修改的功能,你將只需要創建一個新的路由類型
PHP教程那就是說,你可能想要用不同的路由范例.接口Zend_Controller_Router_Interface提供了需要最少的信息來創建路由器,并包含一個單個的辦法.
PHP教程
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教程路由只發生一次:當哀求第一次接收到系統.路由器的意圖是基于哀求的環境決定控制器、動作和可選的參數,并把它們發給哀求.哀求對象接著傳遞給派遣器.如果不可能映射一個路由到一個派遣令牌,路由器對哀求對象就什么也不做.
PHP教程更多關于zend相關內容感興趣的讀者可查看本站專題:《Zend FrameWork框架入門教程》、《php優秀開發框架總結》、《Yii框架入門及常用技巧總結》、《ThinkPHP入門教程》、《php面向對象程序設計入門教程》、《php+mysql數據庫操作入門教程》及《php常見數據庫操作技巧匯總》
PHP教程希望本文所述對大家PHP程序設計有所贊助.
《PHP應用:Zend Framework教程之路由功能Zend_Controller_Router詳解》是否對您有啟發,歡迎查看更多與《PHP應用:Zend Framework教程之路由功能Zend_Controller_Router詳解》相關教程,學精學透。維易PHP學院為您提供精彩教程。
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/7399.html