路由器主要负责解析一个请求而且决定什么module、controller、action被请求;它同时也定义了一种方法来实现用户自定义路由,这也使得它成为最重要的一个MVC组组件。为了方便自定义路由, Yaf摒弃了0.1版本中的自定义路由器方式, 而采用了更为灵活的路由器和路由协议分离的模式。也就是一个固定不变的路由器, 配合各类可自定义的路由协议, 来实现灵活多变的路由策略.
做为一个应用中的路由组件是很重要的,理所固然的路由组件是抽象的,这样容许做为开发者的咱们很容易的设计出咱们自定义的路由协议.然而,默认的路由组件其实已经服务得咱们很好了.记住,若是咱们须要一个非标准的路由协议时候,咱们就能够自定义一个本身的路由协议,而不用采用默认的路由协议。Yaf的路由组件由两部分组成,就是路由和路由协议
路由协议事实上主要负责匹配咱们预先定义好的路由协议,意思就是咱们只有一个路由器,但咱们能够有许多路由协议. 路由器主要负责管理和运行路由链,它根据路由协议栈倒序依次调用各个路由协议, 一直到某一个路由协议返回成功之后, 就匹配成功.
路由的过程发生派遣过程的最开始,而且路由解析仅仅发生一次.路由过程在何控制器动做(Controller, Action)被派遣以前被执行,一旦路由成功,路由器将会把解析出获得的信息传递给请求对象(Yaf_Request_Abstract object), 这些信息包括moduel、controller、action、用户params等. 而后派遣器(Yaf_Dispatcher)就会按照这些信息派遣正确的控制器动做. 路由器也有插件钩子,就是routerStartup和routerShutdown,他们在路由解析先后分别被调用.
php
默认状况下,Yaf的路由器是Yaf_Router, 而默认使用的路由协议是Yaf_Route_Static,是基于HTTP路由的, 它指望一个请求是HTTP请求而且请求对象是使用Yaf_Request_Http
使用路由
使用路由既可让之很复杂,同时也能让它很简单,这是归于你的应用。然而使用一个路由是很简单的,你能够添加你的路由协议给路由器,Yaf为咱们提供了6种路由协议,分别以下:
Yaf_Route_Simple
Yaf_Route_Supervar
Yaf_Route_Static
Yaf_Route_Map
Yaf_Route_Rewrite
Yaf_Route_Regex
下面咱们会分别举例说明如何使用这些路由协议来达到咱们的目的。
首先咱们得了解路由器和路由协议是如何工做的,就是咱们得先获得一个路由器实例,Yaf中经过派遣器的getRouter方法来获得默认的路由器,代码以下: html
获得路由器以后咱们能够用路由器来添加路由协议了。咱们能够经过配置文件来添加路由协议,示例以下 bash
[common] ;自定义路由 ;顺序很重要 routes.regex.type="regex" routes.regex.match="#^/list/([^/]*)/([^/]*)#" routes.regex.route.controller=Index routes.regex.route.action=action routes.regex.map.1=name routes.regex.map.2=value ;添加一个名为simple的路由协议 routes.simple.type="simple" routes.simple.controller=c routes.simple.module=m routes.simple.action=a ;添加一个名为supervar的路由协议 routes.supervar.type="supervar" routes.supervar.varname=r [product : common] ;product节是Yaf默认关心的节, 添加一个名为rewrite的路由协议 routes.rewrite.type="rewrite" routes.rewrite.match="/product/:name/:value"
而后在Bootstrap中经过调用Yaf_Router::addConfig添加定义在配置中的路由协议 dom
默认的路由协议Yaf_Route_Static, 就是分析请求中的request_uri, 在去除掉base_uri之后, 获取到真正的负载路由信息的request_uri片断, 具体的策略是, 根据"/"对request_uri分段, 依次获得Module,Controller,Action, 在获得Module之后, 还须要根据Yaf_Application::$modules来判断Module是不是合法的Module, 若是不是, 则认为Module并无体如今request_uri中, 而把原Module当作Controller, 原Controller当作Action:
使用示例: ide
当只有一段路由信息的时候, 好比对于上面的例子, 请求的URI为/ap/foo, 则默认路由和下面要提到的Yaf_Route_Supervar会首先判断ap.action_prefer, 若是为真, 则把foo当作Action, 不然当作Controller
函数
Yaf_Route_Simple是基于请求中的query string来作路由的, 在初始化一个Yaf_Route_Simple路由协议的时候, 咱们须要给出3个参数, 这3个参数分别表明在query string中Module, Controller, Action的变量名:
使用实例: this
只有在query string中不包含任何3个参数之一的状况下, Yaf_Route_Simple才会返回失败, 将路由权交给下一个路由协议.
spa
Yaf_Route_Supervar和Yaf_Route_Simple类似, 都是在query string中获取路由信息, 不一样的是, 它获取的是一个相似包含整个路由信息的request_uri
使用实例: 插件
在query string中不包含supervar变量的时候, Yaf_Route_Supervar会返回失败, 将路由权交给下一个路由协议.
设计
Yaf_Route_Map议是一种简单的路由协议, 它将REQUEST_URI中以'/'分割的节, 组合在一块儿, 造成一个分层的控制器或者动做的路由结果. Yaf_Route_Map的构造函数接受俩个参数, 第一个参数表示路由结果是做为动做的路由结果,仍是控制器的路由结果. 默认的是动做路由结果. 第二个参数是一个字符串, 表示一个分隔符, 若是设置了这个分隔符, 那么在REQUEST_URI中, 分隔符以前的做为路由信息载体, 而以后的做为请求参数.
使用实例:
Yaf_Route_Rewrite是一个强大的路由协议, 它能知足咱们绝大部分的路由需求:
使用实例:
在这个例子中, 咱们试图匹配Url指定到一个单一的产品, 就像http://domain.com/product/choclolat-bar. 为了实现这点, 咱们在路由协议中传递了2个变量到路由协议Yaf_Route_Rewrite的构造函数其中. 第一个变量('product/:indent')就是匹配的路径, 第二个变量(array变量)是路由到的动做控制器; 路径使用一个特别的标识来告诉路由协议如何匹配到路径中的每个段,这个标识有有两种,能够帮助咱们建立咱们的路由协议,以下所示:
a) :
b) *
冒号(:)指定了一个段,这个段包含一个变量用于传递到咱们动做控制器中的变量,咱们要设置好事先的变量名,好比在上面咱们的变量名就是'ident',所以,假若咱们访问http://domian.com/product/chocoloate-bar将会建立一个变量名为ident而且其值是'chocoloate-bar'的变量,咱们而后就能够在咱们的动做控制器ProductsController/viewAction下获取到它的值:$this->getRequest()->getParam('ident');
星号(*)被用作一个通配符, 意思就是在Url中它后面的全部段都将做为一个通配数据被存储. 例如,若是咱们有路径'path/product/:ident/*'(就是路由协议中设置的第一个变量), 而且咱们访问的Url为http://domain.com/product/chocolate-bar/test/value1/another/value2,那么全部的在'chocolate-bar'后面的段都将被作成变量名/值对,所以这样会给咱们下面的结果:
ident = chocolate-bar
test = value1
another = value2
这种行为也就是咱们日常默认使用的路由协议的行为,记住变量名/值要成对出现,不然像/test/value1/这样的将不会这种另外一个变量,咱们有静态的路由协议部分,这些部分简单地被匹配来知足咱们的路由协议,在咱们的例子中,静态部分就是product; 就像你如今看到的那样,咱们的Yaf_Route_Rewrite路由协议提供给咱们极大的灵活性来控制咱们的路由
到目前为止,咱们以前的路由协议都很好的完成了基本的路由操做,咱们经常使用的也是他们,然而它们会有一些限制,这就是咱们为何要引进正则路由(Yaf_Route_Regex)的缘由. 正则路由给予咱们preg正则的所有力量,但同时也使得咱们的路由协议变得更加复杂了一些.即便是他们有点复杂,我仍是但愿你能好好掌握它,由于它比其余路由协议要灵活一点点. 一开始,咱们先对以前的产品案例改用使用正则路由
使用实例:
你能够看到,咱们如今移动咱们的正则到咱们的path(构造函数的第一个参数)中来了,就像以前的那样,这个正则路由协议如今应该是匹配是一个数字、字母、-和_组成的ident变量的字符提供给咱们,可是,你必定会问,ident变量在哪呢?好,若是你使用了这个正则路由协议,咱们能够经过变量1(one)来获取其值,便可以在控制器里用:$this->getRequest()->getParam(1)来获取,其实这里若是看过正则的都知道这就是反向引用中的\1.然而,你必定会想为何要定义的这么的垃圾,咱们不可以记住或者弄清每个数字表明的是什么变量(其实我刚开始看的时候也是同样的感觉).为了改变这点,正则路由协议的构造函数提供了第3个参数来完成数字到变量名的映射:
这样,咱们就简单的将变量1映射到了ident变量名,这样就设置了ident变量,同时你也能够在控制器里面获取到它的值.
固然, 这个世界上没有绝对的事情. 因此万一如今全部的路由协议都不能知足你的需求, 那么你能够本身实现你本身的路由协议, 你要作的是, 申明你的路由协议实现了Yaf_Route_Interface接口便可。这里就不对自定义路由协议再作过多的说明了。
路由注册的顺序很重要, 最后注册的路由协议, 最早尝试路由, 这就有个陷阱. 请注意.