關於PATHINFO的重寫規則解析

最近比較流行的框架好比laravel,yii國內的thinkphp都提供了以重定url的方式來實現pathinfo的url風格。 php

以thinkphp爲例,提供了名爲 "s"的get參數,只須要將路徑重定向到這個參數上便可,好比nginx下: html


location / {  
    if (!-e $request_filename){  
        rewrite ^/(.*) /index.php?s=$1 last;  
    }  
}



根本不用費大力氣寫一大堆代碼實現所謂的PATH_INFO.


如今laravel和yii2的重寫規則更加簡單,僅僅須要: nginx


location / {
        
        try_files $uri $uri/ /index.php?$args;
}



apache相似的規則:



RewriteEngine on

# If a directory or a file exists, use the request directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward the request to index.php
RewriteRule . index.php



解釋下規則:


當你訪問一個沒法訪問的路徑時,好比 localhost/Index/index 實際上在你的webroot目錄是沒有Index/index目錄或Index/index.html文件的,這時候咱們就須要讓框架來處理請求,將/Index/index 這個路徑交給框架,而框架惟一的入口就是localhost/index.php,因此咱們只須要將該請求重寫到這個url上就能夠了。 laravel

當訪問 web

localhost/index/index?a=1  thinkphp

時,會重定向到: shell

localhost/index.php?a=1 apache

那麼/index/index這個字符串哪去了?答案應該在一個環境變量$_SERVER['REQUEST_URI']或者相似的變量,讓咱們經過Yii2裏面的一個函數來研究一下具體流程: 瀏覽器


protected function resolveRequestUri()
    {
        if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // IIS
            $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
        } elseif (isset($_SERVER['REQUEST_URI'])) {
            $requestUri = $_SERVER['REQUEST_URI'];
            if ($requestUri !== '' && $requestUri[0] !== '/') {
                $requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri);
            }
        } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 CGI
            $requestUri = $_SERVER['ORIG_PATH_INFO'];
            if (!empty($_SERVER['QUERY_STRING'])) {
                $requestUri .= '?' . $_SERVER['QUERY_STRING'];
            }
        } else {
            throw new InvalidConfigException('Unable to determine the request URI.');
        }

        return $requestUri;
    }



這個方法應該是用得到重定向以前的url,也就是你瀏覽器地址欄中所顯示的 /index/index?a=1 這個原始字符串。在nginx和apache中,默認的是$_SERVER['REQUEST_URI']而在iis中略有不一樣,好比$_SERVER['HTTP_X_REWRITE_URL']和$_SERVER['ORIG_PATH_INFO'] yii2

好了,無論它處理過程,咱們只要知道經過這個方法獲得了原始url,而後咱們能夠根據這個url來解析pathinfo吧::

if (!empty($_SERVER['REQUEST_URI']))
    {
      $path = preg_replace('/\?.*$/sD', '', $_SERVER['REQUEST_URI']);
    }



$path獲得了什麼?就是 /index/index ,而後再去根據路由獲得控制器名index和方法名index。


以上只是我我的的猜想,並未深刻yii2框架追根溯源,若有錯誤請指出,不勝感激。

相關文章
相關標籤/搜索