最近比较流行的框架好比laravel,yii国内的thinkphp都提供了以重定url的方式来实现pathinfo的url风格。 php
以thinkphp为例,提供了名为 "s"的get参数,只须要将路径重定向到这个参数上便可,好比nginx下: html
location / { if (!-e $request_filename){ rewrite ^/(.*) /index.php?s=$1 last; } }
如今laravel和yii2的重写规则更加简单,仅仅须要: nginx
location / { try_files $uri $uri/ /index.php?$args; }
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']); }
以上只是我我的的猜想,并未深刻yii2框架追根溯源,若有错误请指出,不胜感激。