PHP 擴展 - 獲取正確的 URI

最近在寫的 Azalea MVC 框架中,類似 Zend Framework 根據 url 來獲取 Controller Action 等參數。在開發環境中,我使用是 Mac 下自帶的 Apache + php_mod 方式,該方式直接獲取 $_SERVER['PATH_INFO'] 即可得到請求的 URI,代碼如下

zval *server, *uri = NULL;
server = &PG(http_globals)[TRACK_VARS_SERVER];
if ((field = zend_hash_str_find(Z_ARRVAL_P(server), ZEND_STRL("PATH_INFO"))) && Z_TYPE_P(field) == IS_STRING) {
    uri = zend_string_copy(Z_STR_P(field));
}

然而在測試環境中,使用的是 Nginx + php_fpm 方式,不知為何 PATH_INFO 屬性并不存在,參考鳥哥的 yaf,得到以下代碼解決

#include "ext/standard/url.h" // for php_url_*

zval *server, *field, *uri = NULL;
server = &PG(http_globals)[TRACK_VARS_SERVER];
do {
    // 還是先找 PHP_INFO
    if ((field = zend_hash_str_find(Z_ARRVAL_P(server), ZEND_STRL("PATH_INFO"))) && Z_TYPE_P(field) == IS_STRING) {
        uri = zend_string_copy(Z_STR_P(field));
        break;
    }
    // 接著找 REQUEST_URI
    if ((field = zend_hash_str_find(Z_ARRVAL_P(server), ZEND_STRL("REQUEST_URI"))) && Z_TYPE_P(field) == IS_STRING) {
        if (strncasecmp(Z_STRVAL_P(field), ZEND_STRL("http://")) &&
                strncasecmp(Z_STRVAL_P(field), ZEND_STRL("https://"))) {
            // not http url
            char *pos = strstr(Z_STRVAL_P(field), "?");
            if (pos) {
                // found query
                uri = zend_string_init(Z_STRVAL_P(field), pos - Z_STRVAL_P(field), 0);
            } else {
                uri = zend_string_copy(Z_STR_P(field));
            }
        } else {
            php_url *urlInfo = php_url_parse(Z_STRVAL_P(field));
            if (urlInfo && urlInfo->path) {
                uri = zend_string_init(urlInfo->path, strlen(urlInfo->path), 0);
            }
            php_url_free(urlInfo);
        }
        break;
    }
    // 最后找 ORIG_PATH_INFO
    if ((field = zend_hash_str_find(Z_ARRVAL_P(server), ZEND_STRL("ORIG_PATH_INFO"))) &&
            Z_TYPE_P(field) == IS_STRING) {
        uri = zend_string_copy(Z_STR_P(field));
        break;
    }
} while (0);

最后附上 Apache 和 Nginx 下的 rewrite 規則 :)

; APACHE
Options -Indexes +FollowSymLinks +ExecCGI
DirectoryIndex index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [L]

; NGINX
location / {
    if (!-e $request_filename) {
        rewrite . /index.php last;
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Welcome 目前網絡上充斥著大量的陳舊信息,讓PHP新手誤入歧途,傳播著錯誤的實踐和糟糕的代碼,這必須得到糾正...
    layjoy閱讀 21,724評論 7 118
  • 更改ip和dnsVi /etc/sysconfig/network-scripts/ifcfg-eth0vi /...
    Xwei_閱讀 1,854評論 0 3
  • 架構師必須知道的26項PHP安全實踐 PHP是一種開源服務器端腳本語言,應用很廣泛。Apache web服務器提供...
    meng_philip123閱讀 6,105評論 1 161
  • 安裝Homebrew 安裝Homebrew ruby -e "$(curl -fsSL https://raw.g...
    nanhangfei閱讀 11,810評論 0 10
  • 動態分配內存初始化的方式 初始化列表(list initialization)對于數組、類、結構體都是試用的。
    lusoer閱讀 211評論 0 0