#### 路由變量
上一篇我們系統學習了下路由的執行和檢查流程,下面就來細化每一個部分的學習,本篇就主要來深入學習下路由變量的定義和使用。
一個應用的路由規則應該在設計之初就規范好,并盡量避免在項目過程中更改路由。
尤其是做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方法調用順序無關。
* * * * *
http://www.hmoore.net/thinkphp/route-master/223111