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,
這樣的話我們就可以通過駝峰的方式正常訪問。操作方法的訪問本身不會受到自動轉換的影響,但是卻會影響到預設模板的渲染輸出。如圖:
這樣的話我們會得到一個找不到檢視檔案的錯誤,解決方案有兩種:
- 將檢視檔案目錄命名為
hello_world
這種形式。 - 在模版渲染輸出時指定檢視檔案的名稱
$this -> fetch('HelloWorld/index');
// 控制器名稱必須按照規範,否則會無法訪問
官方文件說:關閉URL自動轉換之後,必須使用下面的URL地址訪問(控制器名稱必須嚴格使用控制器類的名稱,不包含控制器字尾)。 但實操發現使用hello_world這種訪問方法依然是可以訪問的。
如果你的伺服器環境不支援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完全開發手冊]