Yaf学习之路由

一、前言

  • Yaf的路由组件包括Yaf_RouterYaf_Route_Abstract
  • 路由协议指导框架如何将request_uri解析到modulecontrolleraction,以及如何解析用户提交的参数
  • 一个应用可以注册多个路由协议,最后注册的路由协议最先尝试(优先级最高)
  • 路由解析出来后会被传递给Yaf_Request_Abstract 实例
  • 默认的路由协议是Yaf_Route_Static,在request_uri中以 “/” 分割modulecontrolleraction和参数的键和值

二、添加路由

添加路由有两种方式:通过php程序构造路由协议对象添加,通过配置文件添加。

首先得获取路由,
方法1,通过Yaf_Application对象:

$router = Yaf_Application::app()->getDispacher()->getRouter();

方法2,直接通过Yaf_Dispatcher对象:

$router = Yaf_Dispatcher::getInstance()->getRouter();

本质上都是需要通过Yaf_Dispatcher 获取。

然后在执行Yaf_Applicationrun()方法前添加路由:

$simpleRoute = new Yaf_Route_Simple('m', 'c', 'a');
$router->addRoute('simple_route', $simpleRoute);

上面的代码添加了一个Yaf_Route_Simple路由。

三、路由协议介绍

1. Yaf_Route_Static

这是Yaf的默认路由协议,在request_uri中以 “/” 分割modulecontrolleraction和参数的键和值。如:

/module/controller/action/param1/value1/param2/value2
或
/controller/action/param1/value1/param2/value2

分割处来的第一段,有可能是module,也有可能是controller,如果该module存在,则认为是module,否则认为是controller

为了测试,在application/controllers目录下定义一个UserController,不属于模块。在application/modules/controllers/app目录下定义一个GoodsController,属于app模块。
Yaf学习之路由_第1张图片
* 没有模块的情形(其实是默认模块 index)
访问user控制器:/user/index/a/1/b/1
Yaf学习之路由_第2张图片
解析正常。参数a的值为1,b的值为2。

  • 包含模块的情形
    访问app模块的goods控制器:app/goods/index/id/3
    Yaf学习之路由_第3张图片
    解析正常。参数id的值为3

2. Yaf_Route_Simple

Yaf_Route_Simple路由协议从query_string中解析出modulecontrolleraction,自然用户提交的参数也不例外。
形式如下:

?m=module&c=controller&a=action¶m1=value1¶m2=value2

创建Yaf_Route_Simple时,需要指定query_string中表示modulecontrolleraction的参数名。
将如下代码加在入口文件index.php的$app->run();之前

$router = Yaf_Application::app()->getDispatcher()->getRouter();
    $simpleRoute = new Yaf_Route_Simple('m', 'c', 'a');
    $router->addRoute('simple_route', $simpleRoute);

以上代码表示,query_string中,m参数的值就是module,c参数的值就是controller,a参数的值就是action。如果有的参数没有值,则取默认值。

访问yaf.cc?m=app&c=goods&id=3,测试一下:
Yaf学习之路由_第4张图片

成功定位到了app模块下的goods控制器中的index方法(默认),参数id也解析成功。

3. Yaf_Route_Supervar

Yaf_Route_Supervar 是从一个query_string参数变量中解析modulecontrolleraction和params参数,解析规则同Yaf_Route_Static
形如:

?r=/module/controller/action/param1/value1/param2/value2

还是举个例子好:

$supervarRoute = new Yaf_Route_Supervar('r');
$router->addRoute('supervar_route', $supervarRoute);

接上面的例子,在入口文件index.php中添加以上代码。该代码表示表示从”r” 参数中解析modulecontrolleraction和params参数。

访问yaf.cc/?r=/app/goods/index/c/1/d/2 测试一下:
Yaf学习之路由_第5张图片
成功定位到了app模块下的goods控制器中的index方法,另外参数c、d也解析出来了。

4. Yaf_Route_Regex

顾名思义,该路由协议是通过正则表达式匹配request_uri,创建Yaf_Route_Regex路由协议时,每个正则表达式都必须指定一个modulecontrolleraction组合。

在入口文件index.php中添加如下代码:

$regexRoute = new Yaf_Route_Regex(
    '#product/([0-9]+)/([0-9]+)#', // 必须要用定界符(本例子为"#"),否则报错。鸟哥的Yaf手册中,该例子的正则表达式没有用定界符。版本原因?
    array(
        'module' => 'app',
        'controller' => 'goods',
        'action' => 'detail',
    ),
    array(
        1 => 'cid',
        2 => 'id'
    )
);
$router->addRoute('regex_route', $regexRoute);

该路由匹配如下形式的request_uri:product/1, product/2, product/12。
匹配到之后,定位的模块为app,控制器为goods,动作为detailarray(1=>'id')表示([0-9]+)这个正则表达式匹配到的值作为参数id的值传给detail方法。

app模块中GoodController的detailAction代码如下:

public function detailAction($cid, $id)
{
    Yaf_Application::app()->getDispatcher()->disableView();
    echo "Method: ", __METHOD__, "
"
; echo "Params: "; print_r($this->getRequest()->getParams()); echo "
"
; echo "cid=", $cid, ", id=", $id; }

访问:yaf.cc/product/1/105,结果如下:

Yaf学习之路由_第6张图片
解析OK。

4. Yaf_Route_Rewrite

该路由协议是通过某种模式来匹配request_uri,与Yaf_Route_Regex类似,创建Yaf_Route_Rewrite路由协议时,每个模式都必须指定一个module、controller、action组合。
该路由协议可看成是弱正则的路由协议。

在入口文件index.php中添加如下代码:

$rewriteRoute = new Yaf_Route_Rewrite(
    'user/:name',
    array(
        'controller' => 'user',
        'action' => 'index'
    )
);
$router->addRoute('rewrite_route', $rewriteRoute);

该路由协议将形如/user/a, /user/bc, /user/1 之类的request_uri定位到user控制器的index方法。

访问:yaf.cc/user/lcy/id/3,结果如下:
Yaf学习之路由_第7张图片
控制器和动作定位都OK,lcy这个参数解析出来了,不过另外一种形式的参数/id/3却没解析出来。如果要解析这种形式的参数,必须把模式改成

'user/:name/*'

*是通配符,统一匹配剩下的所有参数。

再次访问,结果如下:
Yaf学习之路由_第8张图片

id 已经解析出来了。

四、总结

关于Yaf的路由,先就学这么多,其实默认路由就很够用了。个人认为路由要简单,不要搞得太复杂,以至于几个月之后自己都看不懂了,还是要专心于业务逻辑上。

你可能感兴趣的:(PHP)