最近比较流行的框架比如laravel,yii国内的thinkphp都提供了以重定url的方式来实现pathinfo的url风格。
以thinkphp为例,提供了名为 "s"的get参数,只需要将路径重定向到这个参数上即可,比如nginx下:
1
2
3
4
5
|
location / {
if
(!-e $request_filename){
rewrite ^/(.*)
/index
.php?s=$1 last;
}
}
|
现在laravel和yii2的重写规则更加简单,仅仅需要:
1
2
3
4
|
location / {
try_files $uri $uri/
/index
.php?$args;
}
|
1
2
3
4
5
6
7
|
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上就可以了。
当访问
localhost/index/index?a=1
时,会重定向到:
localhost/index.php?a=1
那么/index/index这个字符串哪去了?答案应该在一个环境变量$_SERVER['REQUEST_URI']或者类似的变量,让我们通过Yii2里面的一个函数来研究一下具体流程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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']。
好了,不管它处理过程,我们只要知道通过这个方法得到了原始url,然后我们可以根据这个url来解析pathinfo吧::
1
2
3
4
|
if
(!
empty
(
$_SERVER
[
'REQUEST_URI'
]))
{
$path
= preg_replace(
'/\?.*$/sD'
,
''
,
$_SERVER
[
'REQUEST_URI'
]);
}
|