php實現簡單的偽靜態URL的機制介紹

來源:互聯網
上載者:User
  1. RewriteEngine On
  2. RewriteRule ^index\.php$ - [L]
  3. RewriteCond %{REQUEST_FILENAME} !-f
  4. RewriteCond %{REQUEST_FILENAME} !-d
  5. RewriteRule (.+) index.php/$1 [L]
複製代碼

上面的代碼就是將URL結構匯入index.php中,具體的rewrite細節就不贅述了。

2.在PHP中設定一個路由規則設定檔routes.php,我簡單的使用了一個hash數組編寫規則:

  1. /**
  2. *路由設定檔編寫說明:
  3. * 路由配置在一個array數組中,一條記錄代表一個規則
  4. * 其中數組key的資料代表匹配的路徑格式:使用特定的字串標識 如:'/{id}'
  5. * 字串中可以包含特定的變數,所有變數使用大括弧{}包裹起來
  6. * 數組value裡是一個array數組,是對key中路徑中變數進行特定處理
  7. * 變數寫在數組的key中,規範寫在數組的value裡,如:array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index')
  8. * 規範分成兩類:
  9. * 1.格式判斷:比如 '/{id}'=> array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index') 為例,其中'id'=>'/\d+/'就是一個格式判斷,
  10. * 表示id變數只能是數字,格式判斷後面只能使用Regex,由於PHP沒有正則類,所以我指定 '/XXX/'和'#XXX#'格式的字串為Regex
  11. * 2.預設參數:比如 '/{id}'=> array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index') 為例,其中'_m'=>'frontpage'就是一個預設參數,
  12. * 因為前面的路徑沒有_m和_a資訊,所以後面會使用預設參數作為_m和_a的值
  13. *
  14. * 所以對於規則'/{id}'=> array('id'=>'/\d+/','_m'=>'frontpage','_a'=>'index')。我傳入 /3 系統會轉換成 index.php?_m=frontpage&_a=index&id=3
  15. *
  16. * 規則匹配是按照$routes數組的順序逐一匹配,一旦匹配上了就不往下匹配了。所以一些特定的匹配規則要放在前面,通用的放在後面。
  17. * 否則可能導致不執行特定的匹配規則了
  18. */
  19. $routes= array(
  20. '/' => array('_m'=>'wp_frontpage','_a'=>'index'),
  21. '/{id}'=> array('id'=>'/\d+/','_m'=>'wp_frontpage','_a'=>'index'),
  22. '/{_m}/{_a}/{id}'=> array('id'=>'/\d+/'),
  23. '/{_m}/{_a}'=> array()
  24. );
複製代碼

3.路由機制中最複雜也是最重要的一部分,就是解析器。 解析器有兩個類組成(名字可能起的不佳)。 一個是Route,作為整個解析器對外的介面,用於解析規則,匹配和轉換URL,然而它只是一個代理,實際操作不是直接由它直接做的。 一個是RoutePattern,每個RoutePattern執行個體對應規則數組中的一條記錄,一個Route執行個體包含多個RoutePattern,而Route中的所有操作都會調用內部所有RoutePattern執行個體操作,並進行整合。

  1. class Route
  2. {
  3. private static $instance = null;
  4. private $routepatterns=array();
  5. private function __construct()
  6. {
  7. $routes = array();
  8. include ROOT."/routes.php";
  9. foreach($routes as $key=>$value){
  10. $this->routepatterns[]=new RoutePattern($key,$value);
  11. }
  12. if(!isset($_SERVER['PATH_INFO'])) return false;
  13. $urlpath= $_SERVER['PATH_INFO'];
  14. $ismatch=$this->match_url($urlpath);
  15. $strip_urlpath=str_replace('/','',$urlpath);
  16. if(!$ismatch&&!emptyempty($strip_urlpath)){
  17. Content::redirect(PAGE_404);
  18. }
  19. }
  20. /**
  21. * 用路由規則匹配對應的url地址,匹配成功將對應url參數放入$_GET中
  22. * @param string url地址
  23. * @return bool 是否匹配成功
  24. */
  25. public function match_url($urlpath){
  26. foreach($this->routepatterns as $router){
  27. $urlargs=$router->match_url($urlpath);
  28. if($urlargs!==false){
  29. $_GET=array_merge($urlargs,$_GET);
  30. return true;
  31. }
  32. }
  33. return false;
  34. }
  35. public function rewrite_url($urlparams){
  36. foreach($this->routepatterns as $router){
  37. $urlstr=$router->rewrite_url($urlparams);
  38. if($urlstr!==false){
  39. return $urlstr;
  40. }
  41. }
  42. $actualparams=array();
  43. foreach($urlparams as $arg=>$val){
  44. $actualparams[]=$arg."=".urlencode($val);
  45. }
  46. $actualparamstr=implode('&', $actualparams);
  47. $rewriteurl="/index.php";
  48. if(!emptyempty($rewriteurl))$rewriteurl.="?{$actualparamstr}";
  49. return $rewriteurl;
  50. }
  51. public static function init()
  52. {
  53. if (null == self::$instance) {
  54. self::$instance = new Route();
  55. }
  56. return self::$instance;
  57. }
  58. }
  59. class RoutePattern{
  60. //......
  61. }
複製代碼

關於路由設定檔的解析,主要細節全在類RoutePattern中,關於RoutePattern中對規則的解析、URL匹配和轉換URL細節,篇幅和精力有限,今天就不詳細介紹了,下回再仔細分析。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.