## 定義路由
URL地址里面的`index`模塊怎么才能省略呢,默認的URL地址顯得有點長,下面就來說說如何通過路由簡化URL訪問。
我們在路由定義文件(`application/route.php`)里面添加一些路由規則,如下:
~~~
return [
// 添加路由規則 路由到 index控制器的hello操作方法
'hello/:name' => 'index/index/hello',
];
~~~
該路由規則表示所有`hello`開頭的并且帶參數的訪問都會路由到`index`控制器的`hello`操作方法。
路由之前的URL訪問地址為:
~~~
http://tp5.com/index/index/hello/name/thinkphp
~~~
定義路由后就只能訪問下面的URL地址
~~~
http://tp5.com/hello/thinkphp
~~~
>[danger] #### 注意
>****
> 定義路由規則后,原來的URL地址將會失效,變成非法請求。

但這里有一個小問題,如果我們只是訪問
~~~
http://tp5.com/hello
~~~
將發生錯誤,

事實上這是由于路由沒有正確匹配到,我們修改路由規則如下:
~~~
return [
// 路由參數name為可選
'hello/[:name]' => 'index/hello',
];
~~~
使用`[]`把路由規則中的變量包起來,就表示該變量為可選,接下來就可以正常訪問了。
~~~
http://tp5.com/hello
~~~
當`name`參數沒有傳入值的時候,`hello`方法的`name`參數有默認值`World`,所以輸出的內容為 `Hello,World!`
除了路由配置文件中定義之外,還可以采用動態定義路由規則的方式定義,例如在路由配置文件(`application/route.php`)的開頭直接添加下面的方法:
~~~
use think\Route;
Route::rule('hello/:name', 'index/hello');
~~~
完成的效果和使用配置方式定義是一樣的。
無論是配置方式還是通過Route類的方法定義路由,都統一放到路由配置文件`application/route.php`文件中,具體原因后面會揭曉。
>[success]#### 提示:
> * * * * *
>注意路由配置不支持在模塊配置文件中設置。
### 完整匹配
前面定義的路由是只要以hello開頭就能進行匹配,如果需要完整匹配,可以使用下面的定義:
~~~
return [
// 路由參數name為可選
'hello/[:name]$' => 'index/hello',
];
~~~
當路由規則以`$`結尾的時候就表示當前路由規則需要完整匹配。
當我們訪問下面的URL地址的時候:
~~~
http://tp5.com/hello // 正確匹配
http://tp5.com/hello/thinkphp // 正確匹配
http://tp5.com/hello/thinkphp/val/value // 不會匹配
~~~
### 閉包定義
還支持通過定義閉包為某些特殊的場景定義路由規則,例如:
~~~
return [
// 定義閉包
'hello/[:name]' => function ($name) {
return 'Hello,' . $name . '!';
},
];
~~~
或者
~~~
use think\Route;
Route::rule('hello/:name', function ($name) {
return 'Hello,' . $name . '!';
});
~~~
>[success]#### 提示:
> * * * * *
> 閉包函數的參數就是路由規則中定義的變量。
因此,當訪問下面的URL地址:
~~~
http://tp5.com/hello/thinkphp
~~~
會輸出
~~~
Hello,thinkphp!
~~~
### 設置URL分隔符
如果需要改變URL地址中的`pathinfo`參數分隔符,只需要在應用配置文件(`application/config.php`)中設置:
~~~
// 設置pathinfo分隔符
'pathinfo_depr' => '-',
~~~
路由規則定義無需做任何改變,我們就可以訪問下面的地址:
~~~
http://tp5.com/hello-thinkphp
~~~
### 路由參數
我們還可以約束路由規則的請求類型或者URL后綴之類的條件,例如:
~~~
return [
// 定義路由的請求類型和后綴
'hello/[:name]' => ['index/hello', ['method' => 'get', 'ext' => 'html']],
];
~~~
上面定義的路由規則限制了必須是`get`請求,而且后綴必須是`html`的,所以下面的訪問地址:
~~~
http://tp5.com/hello // 無效
http://tp5.com/hello.html // 有效
http://tp5.com/hello/thinkphp // 無效
http://tp5.com/hello/thinkphp.html // 有效
~~~
> 更多的路由參數請參考完全開發手冊的路由參數一節。
### 變量規則
接下來,我們來嘗試一些復雜的路由規則定義滿足不同的路由變量。在此之前,首先增加一個控制器類如下:
~~~
<?php
namespace app\index\controller;
class Blog
{
public function get($id)
{
return '查看id=' . $id . '的內容';
}
public function read($name)
{
return '查看name=' . $name . '的內容';
}
public function archive($year, $month)
{
return '查看' . $year . '/' . $month . '的歸檔內容';
}
}
~~~
添加如下路由規則:
~~~
return [
'blog/:year/:month' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']],
'blog/:id' => ['blog/get', ['method' => 'get'], ['id' => '\d+']],
'blog/:name' => ['blog/read', ['method' => 'get'], ['name' => '\w+']],
];
~~~
在上面的路由規則中,我們對變量進行的規則約束,變量規則使用正則表達式進行定義。
我們看下幾種URL訪問的情況
~~~
// 訪問id為5的內容
http://tp5.com/blog/5
// 訪問name為thinkphp的內容
http://tp5.com/blog/thinkphp
// 訪問2015年5月的歸檔內容
http://tp5.com/blog/2015/05
~~~
### 路由分組
上面的三個路由規則由于都是`blog`打頭,所以我們可以做如下的簡化:
~~~
return [
'[blog]' => [
':year/:month' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']],
':id' => ['blog/get', ['method' => 'get'], ['id' => '\d+']],
':name' => ['blog/read', ['method' => 'get'], ['name' => '\w+']],
],
];
~~~
對于這種定義方式,我們稱之為路由分組,路由分組一定程度上可以提高路由檢測的效率。
### 復雜路由
有時候,我們還需要對URL做一些特殊的定制,例如如果要同時支持下面的訪問地址
~~~
http://tp5.com/blog/thinkphp
http://tp5.com/blog-2015-05
~~~
我們只要稍微改變路由定義規則即可:
~~~
return [
'blog/:id' => ['blog/get', ['method' => 'get'], ['id' => '\d+']],
'blog/:name' => ['blog/read', ['method' => 'get'], ['name' => '\w+']],
'blog-<year>-<month>' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']],
];
~~~
對 `blog-<year>-<month>` 這樣的非正常規范,我們需要使用`<變量名>`這樣的變量定義方式,而不是 `:變量名`方式。
簡單起見,我們還可以把變量規則統一定義,例如:
~~~
return [
// 全局變量規則定義
'__pattern__' => [
'name' => '\w+',
'id' => '\d+',
'year' => '\d{4}',
'month' => '\d{2}',
],
// 路由規則定義
'blog/:id' => 'blog/get',
'blog/:name' => 'blog/read',
'blog-<year>-<month>' => 'blog/archive',
];
~~~
在`__pattern__`中定義的變量規則我們稱之為全局變量規則,在路由規則里面定義的變量規則我們稱之為局部變量規則,如果一個變量同時定義了全局規則和局部規則的話,當前的局部規則會覆蓋全局規則的,例如:
~~~
return [
// 全局變量規則
'__pattern__' => [
'name' => '\w+',
'id' => '\d+',
'year' => '\d{4}',
'month' => '\d{2}',
],
'blog/:id' => 'blog/get',
// 定義了局部變量規則
'blog/:name' => ['blog/read', ['method' => 'get'], ['name' => '\w{5,}']],
'blog-<year>-<month>' => 'blog/archive',
];
~~~
>[danger]### 【 5.1 】使用須知
> * * * * *
> 5.1的路由配置文件改為`route/route.php`,并且支持隨意命名,都會自動加載。并盡量使用方法注冊路由的方式替代數組配置的方式,例如。
>
~~~
use think\facade\Route;
Route::get('blog/:id','blog/get');
Route::get('blog/:name','blog/read');
~~~
- 零、序言
- 一、基礎
- (1)簡介
- (2)安裝
- (3)目錄結構
- (4)運行環境
- (5)入口文件
- (6)資源訪問
- (7)調試模式
- (8)控制器
- (9)視圖
- (10)讀取數據
- (11)總結
- 二、URL和路由
- (1)URL訪問
- (2)參數傳入
- (3)隱藏入口
- (4)定義路由
- (5)URL生成
- (6)總結
- 三、請求和響應
- (1)請求對象
- (2)請求信息
- (3)響應對象
- (4)總結
- 四、數據庫
- (1)準備
- (2)數據庫配置
- (3)原生查詢
- (4)查詢構造器
- (5)鏈式操作
- (6)事務支持
- 五、查詢語言
- (1)查詢表達式
- (2)批量查詢
- (3)快捷查詢
- (4)視圖查詢
- (5)閉包查詢
- (6)獲取值和列
- (7)聚合查詢
- (8)時間查詢
- (9)字符串查詢
- (10)分塊查詢
- 六、模型和關聯
- (1)模型定義
- (2)基礎操作
- (3)讀取器和修改器
- (4)類型轉換和自動完成
- (5)查詢范圍
- (6)輸入和驗證
- (7)關聯
- (8)模型輸出
- 七、視圖和模板
- (1)模板輸出
- (2)分頁輸出
- (3)公共模板
- (4)模板定位
- (5)布局模板
- (6)標簽定制
- (7)輸出替換
- (8)渲染內容
- (9)助手函數
- 八、調試和日志
- (1)第一式:未雨綢繆——頁面Trace
- (2)第二式:初見端倪——異常頁面
- (3)第三式:撥云見日——斷點調試
- (4)第四式:欲窮千里——日志分析
- (5)第五式:運籌帷幄——遠程調試
- 九、API開發
- (1)API版本
- (2)異常處理
- (3)RESTFul
- (4)REST調試
- (5)API調試
- (6)安全建議
- 十、命令行工具
- (1)查看指令
- (2)模塊生成
- (3)控制器生成
- (4)生成類庫映射文件
- (5)生成路由緩存
- (6)生成字段緩存
- (7)指令擴展
- (8)命令行調試
- (9)命令行顏色支持
- (10)命令調用
- 十一、擴展
- (1)函數擴展
- (2)類庫擴展
- (3)驅動擴展
- (4)Composer擴展
- 十二、雜項
- Session
- Cookie
- 驗證碼
- 文件上傳
- 圖像處理
- 單元測試
- 番外篇:學習ThinkPHP5的正確姿勢
- 概念篇:ThinkPHP5名詞解釋
- 附錄A、常見問題集
- 附錄B、3.2和5.0區別
- 附錄C、助手函數
- 附錄D、5.1你必須努力避免的一些問題