-
- RewriteEngine On
- RewriteRule ^index\.php$ - [L]
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule (.+) index.php/$1 [L]
複製代碼 上面的代碼就是將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);
- $strip_urlpath=str_replace('/','',$urlpath);
- if(!$ismatch&&!emptyempty($strip_urlpath)){
- Content::redirect(PAGE_404);
- }
- }
-
- /**
- * 用路由規則匹配對應的url地址,匹配成功將對應url參數放入$_GET中
- * @param string url地址
- * @return bool 是否匹配成功
- */
- public function match_url($urlpath){
- foreach($this->routepatterns as $router){
- $urlargs=$router->match_url($urlpath);
- if($urlargs!==false){
- $_GET=array_merge($urlargs,$_GET);
- return true;
- }
- }
- return false;
- }
-
- public function rewrite_url($urlparams){
- foreach($this->routepatterns as $router){
- $urlstr=$router->rewrite_url($urlparams);
- if($urlstr!==false){
- return $urlstr;
- }
- }
- $actualparams=array();
- foreach($urlparams as $arg=>$val){
- $actualparams[]=$arg."=".urlencode($val);
- }
- $actualparamstr=implode('&', $actualparams);
- $rewriteurl="/index.php";
- if(!emptyempty($rewriteurl))$rewriteurl.="?{$actualparamstr}";
- return $rewriteurl;
- }
-
- public static function init()
- {
- if (null == self::$instance) {
- self::$instance = new Route();
- }
- return self::$instance;
- }
- }
-
- class RoutePattern{
- //......
- }
複製代碼關於路由設定檔的解析,主要細節全在類RoutePattern中,關於RoutePattern中對規則的解析、URL匹配和轉換URL細節,篇幅和精力有限,今天就不詳細介紹了,下回再仔細分析。 |