php偽靜態:php簡單的偽靜態url機制實現
來源:互聯網
上載者:User
曾幾何時,我們公司準備開發一套新的建站系統,決定將以前的架構給ko掉,重新開發一套新的架構來適應新的系統功能。領導們不希望使用外面已有的架構,號稱要開發有自己特色的架構(不懂開發的領導害死人)。於是我們又投入到了新的開發當中。
由於我們的系統支援偽靜態,以前的系統是直接使用伺服器apache或iis內建的rewrite檔案定義規則,而架構中沒有任何路由機制,於是這次架構準備使用新的策略,由php實現路由機制。於是我開始了功能實現的探索之路。
開發之前,我先瞭解‘路由機制’要做什麼,它主要做兩件事。
1.路由機制就是把某一個特定形式的url結構中提煉出來系統對應的參數。舉個例子,如:http://www.cxybl.com/article/1 其中:/article/1 -> ?_m=article&id=1。
2.其次,是將擁有對應參數的url轉換成特定形式的url結構,是上面的過程的逆向過程。由於路由機制隔離了url結構和參數的轉換關係,使的日後結構的變化不會影響下面代碼的執行。
通過上面的瞭解,可以得出要編寫一個路由機制要一下幾步:
1.編寫伺服器apache或iis內建的rewrite檔案,將url結構匯入index.php。
2.一個路由規則設定檔。
3.一個路由解析器,用來解析規則,匹配和轉換url。
於是,我們一一實現其中的每一個部分。
1.rewrite檔案編寫,以apache為例:
<ifmodule mod_rewrite.c>
rewriteengine on
rewriterule ^index\.php$ - [l]
rewritecond %{request_filename} !-f
rewritecond %{request_filename} !-d
rewriterule (.+) index.php/$1 [l]
</ifmodule>
上面的代碼就是將url結構匯入index.php中,具體的rewrite細節就不贅述了。
2.在php中設定一個路由規則設定檔routes.php,我簡單的使用了一個hash數組編寫規則:
/**
*路由設定檔編寫說明:
* 路由配置在一個array數組中,一條記錄代表一個規則
* 其中數組key的資料代表匹配的路徑格式:使用特定的字串標識 如:'/{id}'
* 字串中可以包含特定的變數,所有變數使用大括弧{}包裹起來
* 數組value裡是一個array數組,是對key中路徑中變數進行特定處理
* 變數寫在數組的key中,規範寫在數組的value裡,如:array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index')
* 規範分成兩類:
* 1.格式判斷:比如 '/{id}'=> array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index') 為例,其中'id'=>'/\d+/'就是一個格式判斷,
* 表示id變數只能是數字,格式判斷後面只能使用Regex,由於php沒有正則類,所以我指定 '/xxx/'和'#xxx#'格式的字串為Regex
* 2.預設參數:比如 '/{id}'=> array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index') 為例,其中'_m'=>'frontpage'就是一個預設參數,
* 因為前面的路徑沒有_m和_a資訊,所以後面會使用預設參數作為_m和_a的值
*
* 所以對於規則'/{id}'=> array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index')。我傳入 /3 系統會轉換成 index.php?_m=frontpage&_a=index&id=3
*
* 規則匹配是按照$routes數組的順序逐一匹配,一旦匹配上了就不往下匹配了。所以一些特定的匹配規則要放在前面,通用的放在後面。
* 否則可能導致不執行特定的匹配規則了
*/
$routes= array(
'/' => array('_m'=>'wp_frontpage','_a'=>'index'),
'/{id}'=> array('id'=>'/\d+/','_m'=>'wp_frontpage','_a'=>'index'),
'/{_m}/{_a}/{id}'=> array('id'=>'/\d+/'),
'/{_m}/{_a}'=> array()
);
3.路由機制中最複雜也是最重要的一部分,就是解析器。
解析器有兩個類組成(名字可能起的不佳)。
一個是route,作為整個解析器對外的介面,用於解析規則,匹配和轉換url,然而它只是一個代理,實際操作不是直接由它直接做的。
一個是routepattern,每個routepattern執行個體對應規則數組中的一條記錄,一個route執行個體包含多個routepattern,而route中的所有操作都會調用內部所有routepattern執行個體操作,並進行整合。
class route
{
private static $instance = null;
private $routepatterns=array();
private function __construct()
{
$routes = array();
include root."/routes.php";
foreach($routes as $key=>$value){
$this->routepatterns[]=new routepattern($key,$value);
}
if(!isset($_server['path_info'])) return false;
$urlpath= $_server['path_info'];
$ismatch=$this->match_url($urlpath); 本文連結http://www.cxybl.com/html/wlbc/Php/20120607/28511.html