跟着手册学TP5 —— 路由(一)

Crasph彬 272 0

使用版本为tp5.0.21

路由模式

tp5默认会使用pathinfo的模式,路由规则在route.php中定义,同时可兼容普通模式:

http://tp.hbb/?s=index/index/index&id=1    //普通模式
http://tp.hbb/index/index/index/id/1   //pathinfo模式

其中普通模式的s由config配置中的 var_pathinfo来定义
'url_param_type' 可设置url的解析格式,对于 ?id=2&name=lili这种url无效,例:

http://tp.hbb/index/index/index?id=1&user=3
'url_param_type' = 0 结果: 
array(2) {
  ["id"] => string(1) "1"
  ["user"] => string(1) "3"
}
'url_param_type' = 1 结果:
array(2) {
  ["id"] => string(1) "1"
  ["user"] => string(1) "3"
}
http://tp.hbb/index/index/index/id/1/user/3
'url_param_type' = 0 结果: 
array(2) {
  ["id"] => string(1) "1"
  ["user"] => string(1) "3"
}
'url_param_type' = 1 结果:
array(4) {
  [0] => string(2) "id"
  [1] => string(1) "1"
  [2] => string(4) "user"
  [3] => string(1) "3"
}

当'url_route_must' 以及'url_route_on'都为true时,强制使用路由,必须设置路由后才能访问,否则抛出异常。

路由定义

动态路由

首先,从源码看起

/**
     * 注册路由规则
     * @access public
     * @param string|array $rule    路由规则
     * @param string       $route   路由地址
     * @param string       $type    请求类型
     * @param array        $option  路由参数
     * @param array        $pattern 变量规则
     * @return void
     */
    public static function rule($rule, $route = '', $type = '*', $option = [], $pattern = []){
    。。。。。//省略
        if (is_array($rule) && empty($route)) {
            foreach ($rule as $key => $val) {
                if (is_numeric($key)) {
                    $key = array_shift($val);
                }
                if (is_array($val)) {
                    $route    = $val[0];
                    $option1  = array_merge($option, $val[1]);
                    $pattern1 = array_merge($pattern, isset($val[2]) ? $val[2] : []);
                } else {
                    $option1  = null;
                    $pattern1 = null;
                    $route    = $val;
                }
                self::setRule($key, $route, $type, !is_null($option1) ? $option1 : $option, !is_null($pattern1) ? $pattern1 : $pattern, $group);
            }
        } else {
            self::setRule($rule, $route, $type, $option, $pattern, $group);
        }
    
    }

由源码可以看出路由的定义形式,即

Route::rule('路由表达式','路由地址','请求类型','路由参数(数组)','变量规则(数组)');

已以下代码举例:

微信图片_20181206173606.png

路由结果    http://tp.text/index/5.html
//一般形式
Route::rule('index/:id','index/index/index','get',['ext'=>'html'],['id'=>'\d+']);
//或者
Route::get('index/:id','index/index/index',['ext'=>'html','id'=>'\d+']);

其中type,option,pattern可以省略,但是如果中间有跳着写,则前面的都不能省略,例如:

Route::rule('index/:id','index/index/index','get',['ext'=>'html']);
Route::rule('index/:id','index/index/index','get',[],['id'=>'\d+']);

批量注册

由源码可以看出,当$rule为数组且$rule的值为数组时,可以得出,$rule的值数组三个值分别表示$route,$options,$patten,且里头的值会覆盖最外层定义的$options和$patten

foreach ($rule as $key => $val) {
  if (is_numeric($key)) {
    $key = array_shift($val);
  }
 if (is_array($val)) {
   $route    = $val[0];
   $option1  = array_merge($option, $val[1]);
    $pattern1 = array_merge($pattern, isset($val[2]) ? $val[2] : []);
 } else {
    $option1  = null;
   $pattern1 = null;
    $route    = $val;
 }
 self::setRule($key, $route, $type, !is_null($option1) ? $option1 : $option, !is_null($pattern1) ? $pattern1 : $pattern, $group);
}

由上,得到  http://tp.text/index/5.html   http://tp.text/hello/5.shtml 的形式可定义如下:

Route::rule([
    'index/:id' => 'index/index/index',
    'hello/:id' => ['index/index/hello',['ext'=>'shtml'],['id'=>'\w+']]
],'','GET|POST',['ext'=>'html'],['\d+']);

可是用get或post等简化如下,即省略type参数:

Route::get([
    'index/:id' => 'index/index/index',
    'hello/:id' => ['index/index/hello',['ext'=>'shtml'],['id'=>'\w+']]
],'',['ext'=>'html'],['id'=>'\d+']);

路由分组

路由分组功能允许把相同前缀的路由定义合并分组,这样可以提高路由匹配的效率,不必每次都去遍历完整的路由规则。

例如,我们定义如下的路由

 Route::rule('index/index/:id','index/index/index','get',['ext'=>'html'],['id'=>'\d+']);
 Route::rule('index/hello/:id','index/index/hello','get',['ext'=>'shtml'],['id'=>'\w+']);

则可以把公共的提取出来,形成分组:

Route::group('index',[
       'index/:id'   => 'index/index/index',
       'hello/:id'   =>  ['index/index/hello',['ext'=>'shtml'],['id'=>'[1|2]']]
],['method'=>'get'],['id'=>'\d+']);

另外路由定义成下方则无效,即在外层定义ext并在内层定义ext,暂时未找到原因

Route::group('index',[
       'index/:id'   => 'index/index/index',
       'hello/:id'   =>  ['index/index/hello',['method'=>'get','ext'=>'shtml'],['id'=>'[1|2]']]
],['method'=>'get','ext'=>'html'],['id'=>'\d+']);

组合变量

如果你的路由规则比较特殊,可以在路由定义的时候使用组合变量。

例如:

Route::get('item-<name>-<id>','product/detail',[],['name'=>'\w+','id'=>'\d+']);

组合变量的优势是路由规则中没有固定的分隔符,可以随意组合需要的变量规则,例如路由规则改成如下一样可以支持:

Route::get('item<name><id>','product/detail',[],['name'=>'[a-zA-Z]+','id'=>'\d+']);
Route::get('item@<name>-<id>','product/detail',[],['name'=>'\w+','id'=>'\d+']);

如果需要使用可选变量,则可以使用:

Route::get('item-<name><id?>','product/detail',[],['name'=>'[a-zA-Z]+','id'=>'\d+']);

这贴的实在有点长,那接下篇继续讨论……

支付宝打赏
微信打赏
发表评论
表情 图片 链接 代码

分享
微信
微博
QQ