1. 程式人生 > >TP5.0路由和URL

TP5.0路由和URL

上一篇文章介紹了tp5.0的目錄架構和資料庫的簡單操作。關於資料庫操作這方面我會在其他文章詳細介紹。這篇文章我們主要談一下路由和url。


首先我們要知道ThinkPHP採用單一入口模式訪問應用,對應用的所有請求都定向到應用的入口檔案,系統會從URL引數中解析當前請求的模組、控制器和操作,下面是一個標準的URL訪問格式:
http://域名/index.php/模組/控制器/方法

其中index.php是入口檔案,我們可以通過配置web伺服器的重寫規則將其隱藏。

以Apache為例,我們需要在入口檔案的同級新增.htaccess檔案(官方預設自帶了該檔案),內容如下:

<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] </IfModule>

如果用的phpstudy,規則如下:

<IfModule mod_rewrite.c> 
Options +FollowSymlinks -Multiviews 
RewriteEngine on 
RewriteCond
%{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1] </IfModule>

配置完成後我們就可以使用下面這樣的url地址進行訪問了:
http://域名/index.php/模組/控制器/方法

如果你使用的apache版本使用上面的方式無法正常隱藏index.php,可以嘗試使用下面的方式配置.htaccess檔案:

<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine
on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L] </IfModule>

如果是Nginx環境的話,可以在Nginx.conf中新增:

location / { // …..省略部分程式碼
    if (!-e $request_filename) {
        rewrite  ^(.*)$  /index.php?s=/$1  last;
        break;
    }
}

//模組在ThinkPHP中的概念其實就是應用目錄下面的子目錄,而官方的規範是目錄名小寫,因此模組全部採用小寫命名,無論URL是否開啟大小寫轉換,模組名都會強制小寫。

預設情況下,URL地址中的控制器和操作名是不區分大小寫的,但是如果要訪問一個駝峰命名的控制器,例如我們在index模組下建立一個HelloWorld類檔案:

class HelloWorld
{
        public function index()
        {
            echo 'hello , world !';
        }

}

這時候我們的訪問方式預設為:
http://域名/Index/hello_world/index
而使用http://域名/Index/HelloWorld/index這種方式的訪問則會報一個找不到控制器的錯誤。因為預設的URL訪問是不區分大小寫的,全部都會轉換為小寫的控制器名,除非你在應用配置檔案中,設定了關閉url自動轉換如下:

//設定url中控制器和操作名自動轉換關閉
'url_convert'   => false,

這樣的話我們就可以通過駝峰的方式正常訪問。操作方法的訪問本身不會受到自動轉換的影響,但是卻會影響到預設模板的渲染輸出。如圖:

駝峰命名導致的檢視層異常

這樣的話我們會得到一個找不到檢視檔案的錯誤,解決方案有兩種:

  1. 將檢視檔案目錄命名為hello_world這種形式。
  2. 在模版渲染輸出時指定檢視檔案的名稱 $this -> fetch('HelloWorld/index');

// 控制器名稱必須按照規範,否則會無法訪問

官方文件說:關閉URL自動轉換之後,必須使用下面的URL地址訪問(控制器名稱必須嚴格使用控制器類的名稱,不包含控制器字尾)。 但實操發現使用hello_world這種訪問方法依然是可以訪問的。
關閉url自動轉換後並不影響訪問



如果你的伺服器環境不支援pathinfo方式的URL訪問,可以使用相容方式,例如:
http://域名/index.php?s=index/hello_world/index

變數 S 是可以在應用目錄下的配置檔案中配置的
預設的訪問模組也可以在應用目錄下的配置檔案中配置

5.0版本不再支援普通的url訪問方式。例如:http://域名/index.php?m=index&c=hellow_world&a=index

定義路由

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

定義路由規則後,原來的URL地址將會失效,變成非法請求。

但這裡有一個小問題,如果我們只是訪問 http://tp5.com/hello 將仍然發生模組不存在的錯誤。
事實上這是由於路由沒有正確匹配到,我們修改路由規則如下:

return [
    // 路由引數name為可選
    'hello/[:name]' => 'index/hello',
];

使用[]把路由規則中的變數包起來,就表示該變數為可選,接下來就可以正常訪問了。

除了路由配置檔案中定義之外,還可以採用動態定義路由規則的方式定義,例如在路由配置檔案(application/route.php)的開頭直接新增下面的方法:

use think\Route;
Route::rule('hello/:name', 'index/hello');

完成的效果和使用配置方式定義是一樣的。
無論是配置方式還是通過Route類的方法定義路由,都統一放到路由配置檔案 application/route.php
檔案中

注意路由配置不支援在模組配置檔案中設定。

完整匹配

此段引用官方文件

前面定義的路由是隻要以hello開頭就能進行匹配,如果需要完整匹配,可以使用下面的定義:

return [
// 路由引數name為可選
'hello/[:name]$' => 'index/hello',
];

當路由規則以 $ 結尾的時候就表示當前路由規則需要完整匹配。
當我們訪問下面的URL地址的時候:
http://tp5.com/hello // 正確匹配
http://tp5.com/hello/thinkphp // 正確匹配
http://tp5.com/hello/thinkphp/val/value // 不會匹配

關於路由就簡單寫到這裡,更加複雜的設定請參見[tp5.0完全開發手冊]