#### 路由变量
上一篇我们系统学习了下路由的执行和检查流程,下面就来细化每一个部分的学习,本篇就主要来深入学习下路由变量的定义和使用。
一个应用的路由规则应该在设计之初就规范好,并尽量避免在项目过程中更改路由。
尤其是做API接口开发的时候,URL地址或者路由的变更将会是一个噩梦的开始。
定义路由变量其实就相当于在规划你的URL地址,路由规则应该是全局唯一的,为了确保没有任何的冲突,做好统一的URL规划至关重要。
#### 普通变量定义
路由规则一般由静态地址和动态变量组成,可以包含必须变量和可选变量。
路由规则中的变量有两种定义方式,比较常见的就是下面的写法:
~~~
Route::get('hello/:name','index/index/hello');
~~~
获取路由变量的值可以使用当前Request请求对象直接获取,例如:
~~~
http://tp5.com/hello/thinkphp
~~~
就可以使用下面的两种方法获取变量值:
~~~
// 获取路由变量
request()->route('name');
// 获取当前请求变量
request()->param('name');
~~~
为了更简单的获取,通常我们可以使用参数绑定功能直接把路由变量传入控制器的方法,例如:
~~~
<?php
namespace app\index\controller;
class Index
{
public function hello($name)
{
return 'Hello,' . $name . '!';
}
}
~~~
hello方法的name参数的值就是路由变量name的值。
默认情况下,路由规则并不是完整匹配,所以下面的URL地址都是可以匹配的:
~~~
http://tp5.com/hello/thinkphp
http://tp5.com/hello/thinkphp/city/shanghai
~~~
路由规则之外的变量解析方式一般是`key1/value1/key2/value2`解析为`key1=value1,key2=value2`,也就是说
~~~
http://tp5.com/hello/thinkphp/city/shanghai
~~~
除了会解析路由变量name之外,还会解析另外一个city变量,分别是:
~~~
'name' => 'thinkphp',
'city' => 'shanghai'
~~~
在pathinfo的URL地址中解析的变量我们都称为路由变量,路由变量的获取方式可以是Request请求对象的route或者param方法,但不能使用get方法获取。
如果访问地址是
~~~
http://tp5.com/hello/thinkphp?city=shanghai
~~~
那么city变量就是一个get变量,而不是路由变量,虽然值是相同但类型完全不同。
在某些特殊的情况下,额外路由变量(这里指的是路由规则中定义变量之外的URL变量)的解析规则有所区别,当
~~~
'url_param_type' => 1
~~~
的时候,表示URL变量的解析方式为按顺序解析,这个时候如果访问
~~~
http://tp5.com/hello/thinkphp/city/shanghai
~~~
得到的变量结果就完全不同了,如果输出param方法的结果其实是:
~~~
'name' => 'thinkphp',
0 => 'city',
1 => 'shanghai',
~~~
#### 完整匹配
如果希望仅仅匹配
~~~
http://tp5.com/hello/thinkphp
~~~
而不能访问这种地址
~~~
http://tp5.com/hello/thinkphp/city/shanghai
~~~
就可以使用完整匹配功能,路由定义规则改为:
~~~
Route::get('hello/:name$','index/index/hello');
~~~
路由规则最后用`$`结尾就表示该路由规则是完整匹配的。
(有部分情况下注册的路由规则是自动完整匹配的,比如说资源路由,我们后面会讲到。)
或者使用路由参数
~~~
Route::get('hello/:name','index/index/hello',['complete_match'=>true]);
~~~
两种方式的作用是相同的(实际上使用$结尾的路由定义最终也会解析成`complete_match`参数的方式)。
> 【5.1须知】
可以使用下面的方法定义局部完整匹配
~~~
Route::get('hello/:name','index/index/hello')->completeMatch();
~~~
如果需要全局的路由规则定义都是完整匹配的话,可以直接修改应用的配置参数:
~~~
'route_complete_match' => true
~~~
当开启全局完整匹配后,个别路由规则也支持单独关闭完整匹配,使用下面的方式即可:
~~~
Route::get('hello/:name','index/index/hello',['complete_match'=>false]);
~~~
#### 变量规则
默认情况下,路由变量会匹配所有的字符,但很多时候,我们需要约束变量的规则进行路由匹配:
~~~
Route::get('hello/:name/[:city]','index/index/hello',[],[ 'name' => '[A-Za-z0-9]+' , 'city' => '[A-Za-z]+' ]);
~~~
分别对name和city变量定义了变量规则(采用正则表达式)。
> 【5.1须知】
可以使用下面的方法定义变量规则
~~~
Route::get('hello/:name/[:city]','index/index/hello')
->pattern(['name'=> '[A-Za-z0-9]+' , 'city' => '[A-Za-z]+' ]);
~~~
或者多次调用
~~~
Route::get('hello/:name/[:city]','index/index/hello')
->pattern('name','[A-Za-z0-9]+')
->pattern('city','[A-Za-z]+');
~~~
下面的URL地址会正确匹配
~~~
http://tp5.com/hello/thinkphp2015
http://tp5.com/hello/2015/beijing
~~~
下面的URL地址则无效
~~~
http://tp5.com/hello/think_php
http://tp5.com/hello/thinkphp/2015
~~~
也可以统一对路由变量进行全局规则定义:
~~~
Route::pattern([ 'name' => '[A-Za-z0-9]+' , 'city' => '[A-Za-z]+' ]);
~~~
这样就无需在注册路由规则的时候定义变量规则了,如果同时使用pattern方法和路由定义的时候定义变量规则,那么路由规则定义优先。
~~~
Route::pattern([ 'name' => '[A-Za-z0-9]+' , 'city' => '[A-Za-z]+' ]);
Route::get('hello/:name/[:city]','index/index/hello',[],[ 'name' => '\w+' , 'city' => '[A-Za-z]+' ]);
~~~
实际匹配`hello/:name/:city`的时候name变量的规则为` \w+`。
注意和pattern方法调用顺序无关。
* * * * *
https://www.kancloud.cn/thinkphp/route-master/223111