2.5.1. 简介
Zend_Controller_Router_Rewrite是标准的框架路由器。路由是个过程,在这个过程中它取出URI的端点(跟着基本URL的URI的那部分)并把它分解成参数来决定哪个模块、哪个控制器和控制器中的哪个动作应该接受请求。模块、控制器、动作和其它参数被打包到Zend_Controller_Request_Http对象,接着这个对象由Zend_Controller_Dispatcher_Standard来处理。路由只发生一次:当请求最初被接收和第一个控制器被派遣之前。

Zend_Controller_Router_Rewrite被设计来考虑使用纯php结构时mod_rewrite-like的功能性。它非常宽松地基于Ruby on Rails并且不要求任何先前的web服务器URL rewriting的知识。它被设计来和单个Apache的 mod_rewrite规则(其中之一)一起工作:

RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

或者:

RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1

如果Isapi_Rewrite已经用下列的rewrite规则被安装为一个Isapi扩展, rewrite路由器也可以和IIS web服务器一起使用:

RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css)$)[\w\%]*$)? /index.php [I]
IIS Isapi_Rewrite
当使用IIS,$_SERVER['REQUEST_URI']将要么不存在,要么被设置成一个空串。在这个例子中,Zend_Controller_Request_Http将企图使用被Isapi_Rewrite扩展设置的$_SERVER['HTTP_X_REWRITE_URL']的值。

如果使用 Lighttpd,下面的 rewrite 规则有效:

url.rewrite-once = (".*\?(.*)$" => "/index.php?$1",".*\.(js|ico|gif|jpg|png|css)$" => "$0", "" => "/index.php"
)

2.5.2. 使用路由器
为正确使用rewrite路由器你必须初始化它,添加一些用户定义的路由并注入到控制器。下面的代码示例这个过程:

<?php
/* Create a router */$router = $ctrl->getRouter(); // returns a rewrite router by default
$router->addRoute('user',new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info'))
);

2.5.3. 基本的Rewrite路由器操作
RewriteRouter的核心是用户定义路由的定义。路由通过调用RewriteRouter的addRoute方法和传递一个由类实现的Zend_Controller_Router_Route_Interface的新的实例被添加。例如:

<?php
$router->addRoute('user', new Zend_Controller_Router_Route('user/:username'));
Rewrite 路由器带有四个基本类型的路由(其中一个是特殊的): 第 7.5.6.1 节 “Zend_Controller_Router_Route”第 7.5.6.2 节 “Zend_Controller_Router_Route_Static”第 7.5.6.3 节 “Zend_Controller_Router_Route_Regex”第 7.5.4 节 “缺省路由” *

路由可以被使用无数次来创建链或用户定义的应用程序路由计划。你可以在任何配置中使用任何数量的路由,除了模块路由以外,它最好被用一次并作为通用路由(例如,作为缺省的)。每个路由将在稍后详细描述。

addRoute的第一个参数是路由名。它用来作为权柄从路由器中取得路由(例如,for URL generation purposes)。第二个参数是路由自己。

注意
路由名最普通的用法是通过Zend_View_url助手的方法: <a href="<?= $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>它将导致在 href: user/martel. 

路由是一个简单的过程,这个过程通过所有提供的路由和匹配它的当前请求的URI定义来迭代。当一个正匹配被发现,变量值从路由实例返回并注入到Zend_Controller_Request对象以备将来在派遣器和用户创建的控制器中使用。如果是负匹配,在链中的下个路由被检查。


2.5.4. 缺省路由
Zend_Controller_Router_Rewrite 和缺省路由一起预先配置,它将以controller/action的形式匹配URIs。另外,模块名可以被指定作为第一个路径参数,允许这种module/controller/action形式的URIs。最后,它也将缺省地匹配任何另外的追加到URI的参数-controller/action/var1/value1/var2/value2。

一些路由如何匹配的例子:

// 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/newsmodule == newsInvalid module maps to controller name:
http://example/foocontroller == fooModule + controller:
http://example/blog/archivemodule     == blogcontroller == archiveModule + controller + action:
http://example/blog/archive/listmodule     == blogcontroller == archiveaction     == listModule + controller + action + params:
http://example/blog/archive/list/sort/alpha/date/descmodule     == blogcontroller == archiveaction     == listsort       == alphadate       == desc

缺省路由是存储在RewriteRouter名(index)为’default’的简单的Zend_Controller_Router_Route_Module对象。它被创建多多少少象下面这样:

<?php
$compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request);
$this->addRoute('default', $compat);

如果你不想这个特别的缺省路由在你的路由计划中,你可以重写你自己的‘缺省’路由(例如,把它存储在’default’名下)或用removeDefaultRoutes()完全清除它:

<?php
// Remove any default routes
$router->removeDefaultRoutes();

2.5.5. 基本 URL 和子目录
rewrite路由器可以被用在子目录(例如,http://domain.com/~user/application-root/),在此例中,应用程序 (/~user/application-root)的基本URL应该能自动被Zend_Controller_Request_Http检测到并使用。

如果基本URL被误删除,你可以通过Zend_Controller_Request_Http 和调用 setBaseUrl() 方法(参见第 7.4.2.2 节 “基地址和子目录”)用你自己的基本路径重写它。

<?php
$request->setBaseUrl('/~user/application-root/');

2.5.6. Route Types
2.5.6.1. Zend_Controller_Router_Route
Zend_Controller_Router_Route 是标准的框架路由。它结合了灵活路由定义的易用性。每个路由包含了基本的URL映射(静态的和动态的部分(变量))并且可以被缺省地初始化,也可以根据不同的要求初始化。

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

<?php
$route = new Zend_Controller_Router_Route('author/:username',array('controller' => 'profile','action'     => 'userinfo')
);$router->addRoute('user', $route);

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

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

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

<?php
$values = array('username'   => 'martel','controller' => 'profile','action'     => 'userinfo'
);

稍后,基于这些值,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');
}

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

<?php
$route = new Zend_Controller_Router_Route(':module/:controller/:action/*',array('module' => 'default')
);
$router->addRoute('default', $route);

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

<?php
$route = new Zend_Controller_Router_Route('archive/:year',array('year' => 2006)
);
$router->addRoute('archive', $route);

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

这个例子将导致注入一个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);

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


2.5.6.1.2. 变量请求
当变量请求被设定,第三个参数可以加给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);

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


2.5.6.2. Zend_Controller_Router_Route_Static
上面的例子都使用动态路由--包含模型来匹配的路由。然而有时候,特定的路由被设定成型,启动正则表达式引擎将有过渡的杀伤力。对这种情形的答案是使用静态路由:

<?php
$route = new Zend_Controller_Router_Route_Static('login',array('controller' => 'auth', 'action' => 'login')
);
$router->addRoute('login', $route);

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


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

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

$route = new Zend_Controller_Router_Route_Regex('archive/(\d+)',array('controller' => 'archive','action'     => 'show')
);
$router->addRoute('archive', $route);

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

$values = array(1            => '2006','controller' => 'archive','action'     => 'show'
);

public function showAction()
{$request = $this->getRequest();$year    = $request->getParam(1); // $year = '2006';
}

$route = new Zend_Controller_Router_Route_Regex('archive(?:/(\d+))?',array(1            => '2006','controller' => 'archive','action'     => 'show')
);
$router->addRoute('archive', $route);

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

$route = new Zend_Controller_Router_Route_Regex('archive/(\d+)',array('controller' => 'archive','action' => 'show'),array(1 => 'year')
);
$router->addRoute('archive', $route);

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

$values = array('year'       => '2006','controller' => 'archive','action'     => 'show'
);

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

$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)
);
注意
子模式键必须用整数表示。

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

$route = new Zend_Controller_Router_Route_Regex('archive/(\d+)/page/(\d+)',array( ... ),array('year' => 1)
);

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

$values = array('year'       => '2006',2            => 10,'controller' => 'archive','action'     => 'show'
);

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

$route = new Zend_Controller_Router_Route_Regex('archive/(\d+)',array( ... ),array('year' => 1),'archive/%s'
);

所有这些都已经可能由标准路由对象完成,那么使用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('blog/archive/(\d+)-(.+)\.html',array('controller' => 'blog','action'     => 'view'),array(1 => 'id',2 => 'description'),'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);

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


2.5.7. 使用 Zend_Config with the RewriteRouter
有时候,用新路由更新配置文件比修改代码更方便。这个可能通过addConfig()方法来做。基本上,你创建一个Zend_Config-compatible配置,并在你的代码中读入然后传递给RewriteRouter。

作为例子,考虑下面的 INI 文件:

[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('/path/to/config.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router->addConfig($config, 'routes');

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


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

那就是说,你可能想要用不同的路由范例。接口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);
}

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

2.5. 标准路由器:Zend_Controller_Router_Rewrite相关推荐

  1. 路由器、路由与路由表

    2019独角兽企业重金招聘Python工程师标准>>> 路由器.路由与路由表 路由器就是一台网络设备,它配备多个网络接口卡(NIC),能利用它的网络知识正确转发入口流量. 决定一个入 ...

  2. 安全、稳定的工业蜂窝路由器具有怎样的特性?

    一.前言 传统路由器通过电缆或光纤线路访问Internet,在很多场景或区域下存在着很大的局限性,例如在行驶的火车上,在固定电话稀缺或没有其他接入方式的地区都是十分受限的.随着科技的发展,很多行业应用 ...

  3. 来自未来的路由器,网件R9000夜鹰X10路由器深度评测及拆解!

    作为NETGEAR的新旗舰路由器,其实R9000更像是NETGEAR和TP-Link Talon AD7200争夺802.11AD的一颗重磅炸弹的定位应运而生,那么R9000夜鹰X10值不值得买呢?下 ...

  4. Django REST framework API 指南(11):序列化·关系

    官方原文链接 本系列文章 github 地址 转载请注明出处 Serializer 关系 关系字段用于表示模型关系. 它们可以应用于 ForeignKey,ManyToManyField 和 OneT ...

  5. Cisco产品线一览

    2019独角兽企业重金招聘Python工程师标准>>> 路由器 模块化路由器 ·  Cisco 12000 系列:12008.12012.12016 · Cisco 7500 系列: ...

  6. 如何设置网件gs108e_硬核评测!Wi-Fi 6 到底有多快,如何更快?

    随着光纤入户已经成为家庭常态,"出门用流量.在家用 Wi-Fi" 已经成为一种生活习惯.而当各类视频内容逐步取代了文字内容以后,对于网速的需求也在提升,尤其是家庭入网终端数量不断累 ...

  7. 【RFC3449 网络路径不对称对 TCP 性能的影响】(翻译)

    原文 https://datatracker.ietf.org/doc/html/rfc3449 概述 本文档描述了由于非对称效应而产生的 TCP 性能问题.由于不同的根本原因,这些问题出现在几个接入 ...

  8. 运行 RoCEv2 的网络注意事项

    作        者:  @NGDCN 原文链接: 运行 RoCEv2 的网络注意事项 版        权: 本文由 @NGDCN 于2022-12-15原创发布在 NGDCN,未经许可,禁止转载. ...

  9. PPTP配置实例(HiPER ReOS 2008 ×××配置手册)

    (一).配置HiPER作为PPTP服务器 图1 方案--HiPER作为PPTP服务器 在本方案中,某公司总部在上海.在北京有一个分公司希望可以实现两地局域网内部资源的相互访问.该公司还有一些出差和远程 ...

  10. 计算机网络 自顶向下(5)链路层——学习笔记

    · 概述: · 结点:任何运行链路了层协议的任何设备.包括主机.路由器.交换机和WiFi接入点. · 链路:沿着通信路径连接相邻结点的通信信道称为链路.数据报必须通过沿端到端路径上各段链路传输. · ...

最新文章

  1. 点击拖动放大该图片大小
  2. 什么数字万用表可以测量噪声?
  3. CentOS 7 程序自启动的问题
  4. 化工原理(过滤和沉淀)
  5. kafka控制台模拟消费_Kafka 详解
  6. Linux第一条指令地址,arm-linux 启动代码分析——stage1 (1)
  7. Python已成美国顶尖高校中最受欢迎的入门编程语言
  8. hfss和matlab,hfss和MATLAB联合仿真
  9. J2EE数据库后台开发步骤(附HQL使用教程)
  10. 微信公众号迁移具体内容
  11. Docker下部署wordpress
  12. apt-get无法获取kubelet kubeadm kubectl包
  13. 这种div高度自适应确定你知道吗?
  14. leetcode动态规划
  15. 阶段3 2.Spring_08.面向切面编程 AOP_1 AOP的概念
  16. Xcode编译后运行程序Killed: -9,因为签名有问题
  17. jvm 调优 2020.09.07
  18. Spring中bean的生命周期
  19. dns服务器对网速有影响吗,更换DNS服务器可以提高网速吗?
  20. 如何制作DUN-14条形码

热门文章

  1. easyui源码翻译1.32--Droppable(放置)
  2. Oracle建立用户和表空间
  3. The Furthest Distance In The World
  4. 深入Managed DirectX9(十五)
  5. 七夕出手,这本情话秘籍请收好
  6. 利用R语言美化决策树
  7. 【Android自学日记】【转】Android Fragment 真正的完全解析(上)
  8. linux输出 /dev/null
  9. JWT结合Springboot+shiro,session、token同时存在来应对不同的业务场景(物联网设备管理及开放api)...
  10. iOS:选择器控件UIPickerView的详解和演示