啓用路由
要使用路由功能,前提是你的URL支持PATH_INFO,並且在項目配置文件中開啓路由:
- 'URL_ROUTER_ON' => true, //開啓路由
- 'URL_ROUTE_RULES'=>array(
- 'news/:year/:month/:day' => array('News/archive', 'status=1'),
- 'news/:id' => 'News/read',
- 'news/read/:id' => '/news/:1',
- ),
路由定義
路由規則的定義方式如下:
- '路由表達式'=>'路由地址和額外參數'
路由表達式
路由表達式包括規則路由和正則路由的定義表達式,只能使用字符串。表達式 | 示例 |
---|---|
正則表達式 | /^blog\/(\d+)$/ |
規則表達式 | blog/:id |
路由表達式支持的正則定義必須以“/”開頭,否則就視爲規則表達式。也就是說如果採用
- '#^blog\/(\d+)$#'
- '/^new\/(\d{4})\/(\d{2})$/' => 'News/achive?year=:1&month=:2',
更多的關於如何定義正則表達式就不在本文的描述範疇了。
規則表達式
3.0的規則路由是從2.1的簡單路由進化而來,雖然無法完美實現正則路由的功能,但是相比簡單路由確實增強了不少,而且比正則路由更方便定義和容易理解。
規則表達式通常包含靜態地址和動態地址,或者兩種地址的結合,例如下面都屬於有效的規則表達式:
- 'my'=>'Member/myinfo', // 靜態地址路由 類似於之前版本的簡單路由
- 'blog/:id'=>'Blog/read', // 靜態地址和動態地址結合
- 'new/:year/:month/:day'=>'News/read', // 靜態地址和動態地址結合
- ':user/:blog_id'=>'Blog/read',// 全動態地址
每個參數中以“:”開頭的參數都表示動態參數,並且會自動對應一個GET參數,例如:id表示該處匹配到的參數可以使用$_GET['id']方式獲取,:year :month :day 則分別對應$_GET['year'] $_GET['month'] $_GET['day']。
數字約束
支持對變量的類型檢測,但僅僅支持數字類型的約束定義,例如
- 'blog/:id\d'=>'Blog/read',
規則排除
非數字變量支持簡單的排除功能,主要是起到避免解析混淆的作用,例如:
- 'news/:cate^add|edit|delete'=>'News/category'
- 'new/:cate'=>'News/category'
完全匹配
規則匹配檢測的時候只是對URL從頭開始匹配,只要URL地址包含了定義的路由規則就會匹配成功,如果希望完全匹配,可以使用$符號,例如:
- 'new/:cate$'=> 'News/category',
- http://serverName/index.php/new/info
而
- http://serverName/index.php/new/info/2
如果是採用
- 'new/:cate'=> 'News/category',
路由地址和額外參數
路由地址和額外參數表示前面的路由表達式最終需要路由到的地址並且允許隱式傳入URL裏面沒有的一些參數,這裏允許使用字符串或者數組方式定義,支持下面5種方式定義:定義方式 | 定義格式 |
---|---|
方式1:路由到內部地址(字符串) | '[分組/模塊/操作]?額外參數1=值1&額外參數2=值2...' |
方式2:路由到內部地址(數組)參數採用字符串方式 | array('[分組/模塊/操作]','額外參數1=值1&額外參數2=值2...') |
方式3:路由到內部地址(數組)參數採用數組方式 | array('[分組/模塊/操作]',array('額外參數1'=>'值1','額外參數2'=>'值2'...)) |
方式4:路由到外部地址(字符串)301重定向 | '外部地址' |
方式5:路由到外部地址(數組)可以指定重定向代碼 | array('外部地址','重定向代碼') |
- 'blog/:id'=>'/blog/read/id/:1'
- 'blog/:id'=>'blog/read/'
/member/avatar/id/123_small的話,只能使用:
- 'avatar/:id'=>'/member/avatar/id/:1_small'
採用重定向到外部地址通常對網站改版後的URL遷移過程非常有用,例如:
- 'blog/:id'=>'http://blog.thinkphp.cn/read/:1'
在路由跳轉的時候支持額外傳入參數對(額外參數指的是不在URL裏面的參數,隱式傳入需要的操作中,有時候能夠起到一定的安全防護作用,後面我們會提到),支持“額外參數1=值1&額外參數2=值2”或者array('額外參數1'=>'值1','額外參數2'=>'值2'...)這樣的寫法,可以參考不同的定義方式選擇。例如:
- 'blog/:id'=>'blog/read/?status=1&app_id=5',
- 'blog/:id'=>array('blog/read/?status=1&app_id=5'),
- 'blog/:id'=>array('blog/read/','status=1&app_id=5'),
- 'blog/:id'=>array('blog/read/',array('status'=>1,'app_id'=>5)),
實例說明
通過上面的講解,我們瞭解瞭如何定義路由規則,下面我們來舉個例子加深印象。假設我們定義了News控制器如下(代碼實現僅供參考):
- class NewsAction extends Action{
- public function read(){
- $New = M('New');
- if(isset($_GET['id'])) {
- // 根據id查詢結果
- $data = $New->find($_GET['id']);
- }elseif(isset($_GET['name'])){
- // 根據name查詢結果
- $data = $New->getByName($_GET['name']);
- }
- $this->data = $data;
- $this->display();
- }
- public function archive(){
- $New = M('New');
- $year = $_GET['year'];
- $month = $_GET['month'];
- $begin_time = strtotime($year . $month . "01");
- $end_time = strtotime("+1 month", $begin_time);
- $map['create_time'] = array(array('gt',$begin_time),array('lt',$end_time));
- $map['status'] = 1;
- $list = $New->where($map)->select();
- $this->list = $list;
- $this->display();
- }
- }
- 'URL_ROUTE_RULES' => array( //定義路由規則
- 'new/:id\d' => 'News/read',
- 'new/:name' => 'News/read',
- 'new/:year\d/:month\d' => 'News/archive',
- ),
- http://serverName/index.php/new/8
- http://serverName/index.php/News/read/id/8
- http://serverName/index.php/new/hello
- http://serverName/index.php/News/read/name/hello
- http://serverName/index.php/new/2012/03
- http://serverName/index.php/News/archive/year/2012/month/03
1、調整定義順序
路由定義改成:
- 'URL_ROUTE_RULES' => array( //定義路由規則
- 'new/:year\d/:month\d' => 'News/archive',
- 'new/:id\d' => 'News/read',
- 'new/:name' => 'News/read',
- ),
- http://serverName/index.php/new/2012/03
2、利用完全匹配功能
現在我們來利用路由的完全匹配定義功能,把路由定義改成:
- 'URL_ROUTE_RULES' => array( //定義路由規則
- 'new/:id\d$' => 'News/read',
- 'new/:name$' => 'News/read',
- 'new/:year\d/:month\d$' => 'News/archive',
- ),
所以,如果我們訪問
- http://serverName/index.php/new/2012/03/01
3、利用正則路由
當然,解決問題的辦法總是不止一種,對於複雜的情況,我們不要忘了使用正則路由規則定義,在你找不到解決方案的時候,正則路由總能幫到你。
要實現上面的同樣路由功能的話,還可以用下面的規則定義:
- 'URL_ROUTE_RULES' => array( //定義路由規則
- '/^new\/(\d+)$/' => 'News/read?id=:1',
- '/^new\/(\w+)$/' => 'News/read?name=:1',
- '/^new\/(\d{4})\/(\d{2})$/' => 'News/achive?year=:1&month=:2',
- ),