热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Yaf零基础学习总结8-Yaf中的路由和路由协议

路由器主要负责解析一个请求并且决定什么module、controller、action被请求;它同时也定义了一种方法来实现用户自定义路由,这也使得它成为最重要的一个MVC组组件
路由器主要负责解析一个请求并且决定什么module、controller、action被请求;它同时也定义了一种方法来实现用户自定义路由,这也使得它成为最重要的一个MVC组组件。为了方便自定义路由, Yaf摒弃了0.1版本中的自定义路由器方式, 而采用了更为灵活的路由器和路由协议分离的模式。也就是一个固定不变的路由器, 配合各种可自定义的路由协议, 来实现灵活多变的路由策略. 

作为一个应用中的路由组件是很重要的,理所当然的路由组件是抽象的,这样允许作为开发者的我们很容易的设计出我们自定义的路由协议.然而,默认的路由组件其实已经服务得我们很好了.记住,如果我们需要一个非标准的路由协议时候,我们就可以自定义一个自己的路由协议,而不用采用默认的路由协议。Yaf的路由组件由两部分组成,就是路由和路由协议 

路由协议事实上主要负责匹配我们预先定义好的路由协议,意思就是我们只有一个路由器,但我们可以有许多路由协议. 路由器主要负责管理和运行路由链,它根据路由协议栈倒序依次调用各个路由协议, 一直到某一个路由协议返回成功以后, 就匹配成功. 

路由的过程发生派遣过程的最开始,并且路由解析仅仅发生一次.路由过程在何控制器动作(Controller, Action)被派遣之前被执行,一旦路由成功,路由器将会把解析出得到的信息传递给请求对象(Yaf_Request_Abstract object), 这些信息包括moduel、controller、action、用户params等. 然后派遣器(Yaf_Dispatcher)就会按照这些信息派遣正确的控制器动作. 路由器也有插件钩子,就是routerStartup和routerShutdown,他们在路由解析前后分别被调用. 

默认的路由协议

默认情况下,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方法来得到默认的路由器,代码如下: 


getRouter();
?>


得到路由器之后我们可以用路由器来添加路由协议了。我们可以通过配置文件来添加路由协议,示例如下 
[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添加定义在配置中的路由协议 
[php] view plaincopy
getRouter();  
                /** 
                 * 添加配置中的路由 
                 */  
                $router->addConfig(Yaf_Registry::get("config")->routes);  
        }  
}  



默认路由协议Yaf_Route_Static

默认的路由协议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: 

使用示例: 
[php] view plaincopy
 '默认模块',  
        'controller' => 'foo',  
        'action'     => 'bar',  
        'params'     => array(  
             'dummy' => 1,  
        )  
     )  
  
     /** 
      * 而如果在配置文件中定义了ap.modules="Index,Foo", 
      * 则此处就会认为foo是一个合法模块, 则结果如下 
      */  
      array(  
        'module'     => 'foo',  
        'controller' => 'bar',  
        'action'     => 'dummy',  
        'params'     => array(  
             1 => NULL,  
        )  
     )  



当只有一段路由信息的时候, 比如对于上面的例子, 请求的URI为/ap/foo, 则默认路由和下面要提到的Yaf_Route_Supervar会首先判断ap.action_prefer, 如果为真, 则把foo当做Action, 否则当做Controller 

Yaf_Route_Simple

Yaf_Route_Simple是基于请求中的query string来做路由的, 在初始化一个Yaf_Route_Simple路由协议的时候, 我们需要给出3个参数, 这3个参数分别代表在query string中Module, Controller, Action的变量名: 

使用实例: 
[php] view plaincopy
addRoute("name", $route);  
     /** 
      * 对于如下请求: "http://domain.com/index.php?c=index&a=test 
      * 能得到如下路由结果 
      */  
      array(  
        'module'     => '默认模块',  
        'controller' => 'index',  
        'action'     => 'test',  
        )  


只有在query string中不包含任何3个参数之一的情况下, Yaf_Route_Simple才会返回失败, 将路由权交给下一个路由协议. 


Yaf_Route_Supervar

Yaf_Route_Supervar和Yaf_Route_Simple相似, 都是在query string中获取路由信息, 不同的是, 它获取的是一个类似包含整个路由信息的request_uri 

使用实例: 
[php] view plaincopy
addRoute("name", $route);  
     /** 
     * 对于如下请求: "http://domain.com/index.php?r=/a/b/c 
     * 能得到如下路由结果 
     */  
     array(  
     'module'     => 'a',  
     'controller' => 'b',  
     'action'     => 'c',  
     )  


在query string中不包含supervar变量的时候, Yaf_Route_Supervar会返回失败, 将路由权交给下一个路由协议. 

Yaf_Route_Map

Yaf_Route_Map议是一种简单的路由协议, 它将REQUEST_URI中以'/'分割的节, 组合在一起, 形成一个分层的控制器或者动作的路由结果. Yaf_Route_Map的构造函数接受俩个参数, 第一个参数表示路由结果是作为动作的路由结果,还是控制器的路由结果. 默认的是动作路由结果. 第二个参数是一个字符串, 表示一个分隔符, 如果设置了这个分隔符, 那么在REQUEST_URI中, 分隔符之前的作为路由信息载体, 而之后的作为请求参数. 

使用实例: 

[php] view plaincopy
 'products',  
         'action' => 'view'  
       )  
     );  
     //使用路由器装载路由协议  
     $router->addRoute('product', $route);  


在这个例子中, 我们试图匹配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

到目前为止,我们之前的路由协议都很好的完成了基本的路由操作,我们常用的也是他们,然而它们会有一些限制,这就是我们为什么要引进正则路由(Yaf_Route_Regex)的原因. 正则路由给予我们preg正则的全部力量,但同时也使得我们的路由协议变得更加复杂了一些.即使是他们有点复杂,我还是希望你能好好掌握它,因为它比其他路由协议要灵活一点点. 一开始,我们先对之前的产品案例改用使用正则路由 

使用实例: 

[php] view plaincopy
 'products',  
      'action' => 'view'  
     )  
   );  
   $router->addRoute('product', $route);  


你可以看到,我们现在移动我们的正则到我们的path(构造函数的第一个参数)中来了,就像之前的那样,这个正则路由协议现在应该是匹配是一个数字、字母、-和_组成的ident变量的字符提供给我们,但是,你一定会问,ident变量在哪呢?好,如果你使用了这个正则路由协议,我们可以通过变量1(one)来获取其值,即可以在控制器里用:$this->getRequest()->getParam(1)来获取,其实这里如果看过正则的都知道这就是反向引用中的\1.然而,你一定会想为什么要定义的这么的垃圾,我们不能够记住或者弄清每一个数字代表的是什么变量(其实我刚开始看的时候也是一样的感受).为了改变这点,正则路由协议的构造函数提供了第3个参数来完成数字到变量名的映射: 

[php] view plaincopy
 'products',  
       'action' => 'view'  
     ),  
     array(  
       //完成数字到字符变量的映射  
       1 => 'ident'  
     )  
   );  
   $router->addRoute('product', $route);  


这样,我们就简单的将变量1映射到了ident变量名,这样就设置了ident变量,同时你也可以在控制器里面获取到它的值. 

自定义路由协议

当然, 这个世界上没有绝对的事情. 所以万一现在所有的路由协议都不能满足你的需求, 那么你可以自己实现你自己的路由协议, 你要做的是, 申明你的路由协议实现了Yaf_Route_Interface接口即可。这里就不对自定义路由协议再做过多的说明了。 

路由注册的顺序很重要, 最后注册的路由协议, 最先尝试路由, 这就有个陷阱. 请注意.


推荐阅读
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • MVC设计模式的介绍和演化过程
    本文介绍了MVC设计模式的基本概念和原理,以及在实际项目中的演化过程。通过分离视图、模型和控制器,实现了代码的解耦和重用,提高了项目的可维护性和可扩展性。详细讲解了分离视图、分离模型和分离控制器的具体步骤和规则,以及它们在项目中的应用。同时,还介绍了基础模型的封装和控制器的命名规则。该文章适合对MVC设计模式感兴趣的读者阅读和学习。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 数据库锁的分类和应用
    本文介绍了数据库锁的分类和应用,包括并发控制中的读-读、写-写、读-写/写-读操作的问题,以及不同的锁类型和粒度分类。同时还介绍了死锁的产生和避免方法,并详细解释了MVCC的原理以及如何解决幻读的问题。最后,给出了一些使用数据库锁的实际场景和建议。 ... [详细]
  • ps:写的第一个,不足之处,欢迎拍砖---只是想用自己的方法一步步去实现一些框架看似高大上的小功能(比如说模型中的toArraytoJsonsetAtt ... [详细]
  • 今天写一篇blog,已经多长时间没有更了,两个月了吧,没办法,现在银行开发,不能连外网,天天用虚拟机,真烦今天随手写点东西,主要是这两天对于springboot启动的分析,有所领悟 ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • ElasticSearch成功安装完毕。 测试数据添加出现{  error:{    root_cause ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
author-avatar
闻雪儿1116_414
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有