幾個概念:
THINKPHP 是一個MVC架構,使用PATHINFO解析出分組名,模組名,方法名,以及參數。
PATHINFO:就是 http://localhost/index.php/Home/Index/index/a/1/b/2?c=3 中的紅色部分,注意,c=3並不是pathinfo的一部分,它是一個query參數。PATHINFO指的是URL中的路徑實際上不存在的時候,apache或nginx等通過一定的手段將這個不存在路徑儲存到環境變數 $_SERVER['PATH_INFO']中,也可以將它轉化為$_GET['s']參數,TP也可以識別。
也就是說當你訪問THINKPHP項目的時候,你實際上訪問的只是入口檔案index.php ,不管你後面有多長的路徑,都是實際不存在的,轉化成PATHINFO或$_GET['s']了而已。
那麼THINKPHP就是根據PATHINFO,從中提取出 分組名,模組名,方法名,以及將剩餘的部分轉化為$_GET變數,比如TP從PATHINFO字串中提取'Home'字串,將其儲存到$_GET['g'] ,$_GET['m']='Index' ;$_GET['a']='index' ;$_GET['a']=1 ;$_GET['b']=2。不信你可以隨便在某個模組方法下 dump('$_GET')看看。
之後Tp就是根據$_GET['g'],$_GET['m'],$_GET['a']來載入執行個體化對應分組下的模組類,並執行對應的方法。
關於URL詳細的解析流程,請看 ThinkPHP/Lib/Core/Dispatcher.class.php 核心類。
URL路由:
URL路由--Url Router,指的是,在TP進行常規url解析之前,先檢測路由,如果發現有路由規則匹配當前的PATHINFO,那麼URL解析則交給路由處理。
路由規則是由多條 rule=>router 規則群組成的數組。
路由處理過程大概如下:
1.遍曆路由規則rule,與當前PATHINFO字串進行匹配,如果合法,則從PATHINFO中取出所需要的字串。
2.路由中每條規則對應一個router,router中指定對應的模組以及方法,模組和方法可以用第1步中匹配到的字串進行動態替代。
3.將剩餘的參數都解析並寫入到$_GET中。
路由規則:首先在設定檔中開啟路由,"URL_ROUTER_ON"=>true;然後定義路由規則,路由規則也在設定檔中,參數名為 URL_ROUTE_RULES ,它是一個數組。假設我們開啟一個url:http://localhost/index.php/list/2/p/1 ,我們需要訪問id為1分類列表頁,並且p是頁碼,第一頁。PATHINFO字串為:list/2/p/1 我們需要將它定位到 listAction.class.php 模組中的 index方法,以及將p作為分頁參數寫入到$_GET中定義路由:'URL_ROUTE_RULES'=>array('list/:id/p/:p'=>'Home/list/index'),這樣PATHINFO中的2將被寫入到$_GET['id']=2, 同時 p 對應$_GET['p']=1 ,規則重新導向到Home分組下的list模組index方法,我們只需要在index方法中直接擷取$_GET['id'],以及$_GET['p']即可,實際訪問效果等同於 http://localhost/index.php/Home/list/index?id=2&p=1假如我們要嚴格限定id和p的類型是數字,那麼我們應該這樣做'list/:id\d/p/:p\d'=>'Home/list/index'\d表示數字類型。複雜一點的,假如PATHINFO為 del/10 。要調用article模組下的del方法,並將10作為id傳遞給它規則應該這樣寫“:a/:id\d”=>'Home/article/:1'首先,將del這一段作為一個變數去匹配,:a :b都可以,10也作為一個變數,指定為:id 並且類型要求是整型。在右側router中,通過:1可以使用左側第一個變數,:2 :3依次類推。再假設,我們禁止匹配add/10中的add,規則只需要稍加改動,如下:“:a^add/:id\d”=>'Home/article/:1'如果要禁止多個關鍵詞,則只需要用|拼接,比如 ^add|del|get 如果右側router預設需要帶有參數,可以直接將參數加在?後面,比如“:a^add/:id\d”=>'Home/article/:1?p=1'也可以將右側router寫成數組形式,比如“:a^add/:id\d”=>array('Home/article/:1','p=1&p1=2&p3=3')如果你需要
完整匹配整個PATHINFO,只需要在rule的結尾加上
$,比如list/:id$ 可以匹配 list/10,但是無法匹配list/10/p/1把$拿掉則都可以匹配。上面所講的都是我們程式內部重新導向,實際URL並不會發生跳轉,如果我們想做一個redirect的跳轉,只需要右側router以http://開頭或者以 '/' 開頭即可。比如'list/:id'=>'/artlist/:1' 這樣當我們訪問 http://localhost/list/10的時候,瀏覽器會發生跳轉,跳轉到 http://localhost/artlist/10以上是TP自定定義的一些規則,那麼當以上規則無法滿足你的複雜需求時怎麼辦?
正則路由可以協助你 。正則路由與普通路由的區別是,左側rule不需要記住複雜的文法,我們只需要根據正則文法,直接匹配PATHINFO,右側通過 :1 :2 :3調用即可。比如'/^list\/(\d+)/is'=>'Home/artlist/index?id=:1'注意事項:1.路由不會迴圈匹配,當匹配一次以後將跳出迴圈。2.當路由中同時包含 ^排除關鍵字 和 \指定類型的時候,應當將 ^放在\前面,比如 :d^add|del\s