调整nginx配置支持ThinkPHP的PATH_INFO模式
[文章作者:磨延城 转载请注明原文出处: https://mo2g.com/view/105/ ]
最初公司的平台是让别的互联网公司承包的,网站基于ThinkPHP开发,部署在lamp环境上运行两个月了,后来综合评估了一下,还是觉得更换为lnmp环境更适合.在本地平台测试的时候发现,基于pathinfo重写规则的ThinkPHP在nginx下不兼容,官方手册也只是简单的提到低版本nginx不支持pathinfo模式,并没有过多的说明.
最初公司的平台是让别的互联网公司承包的,网站基于ThinkPHP开发,部署在lamp环境上运行两个月了,后来综合评估了一下,还是觉得更换为lnmp环境更适合。在本地平台测试的时候发现,基于pathinfo重写规则的ThinkPHP在nginx下不兼容,官方手册也只是简单的提到低版本nginx不支持pathinfo模式(其实最新版1.6一样不支持),并没有过多的说明。
项目正在使用的apache的重写规则如下:
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
而官方手册上给出的nginx重写规则如下:
if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; break; }
显然不能满足需求,我需要的是类似下边的重写规则:
if ( !-e $request_filename) { rewrite ^/(.*)$ /index.php/$1 last; }
于是在网上搜索资料,发现大部分都是无脑采集的,耗费了一些时间,还好找到了有用的线索,整理了一番得出答案,顺便记录一下,或许能帮到更多人。
ThinkPHP或其他框架所谓的PATH_INFO模式,其实就是依赖于PHP的超全局变量$_SERVER['PATH_INFO'],现在的问题在于这个变量中保存的信息,很可能会因为服务器的环境的不同而不同。有兴趣的朋友可以在apache环境中,跟Nginx环境中分别试试下边的代码:
<?php var_dump($_SERVER['PATH_INFO']);
输出结果会告诉你,为什么nginx不支持所谓的PATH_INFO模式。
接下来就直入主题,编辑Nginx的配置文件,给Nginx添加PATH_INFO变量。
1)去掉$符号,让nginx最大限度的匹配php文件后跟着的路径
2)给Nginx环境添加PATH_INFO变量
3)对SCRIPT_NAME变量做判断调整
例如原来的配置如下:
location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $root$fastcgi_script_name; include fastcgi_params; }
修改如下:
location ~ \.php { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $root$fastcgi_script_name; include fastcgi_params; set $real_script_name $fastcgi_script_name; if ($fastcgi_script_name ~ ^(.+\.php)(/.+)$) { set $real_script_name $1; #(.+\.php)为当前运行的PHP文件名 set $path_info $2; #(/.+)的值为路径信息 } fastcgi_param SCRIPT_NAME $real_script_name; fastcgi_param PATH_INFO $path_info; }
其中$root根据自己的网站根目录设定,比如网站存在/www/mo2g.com时,设定如下
set $root /www/mo2g.com; root $root;
后续:由于项目是基于ThinkPHP2.x开发的,才发现最新版的ThinkPHP3.2.1已经对不支持PATH_INFO的情况做了相应处理,以下是手册中的一段说明:
新版内置了通过对 ORIG_PATH_INFO , REDIRECT_PATH_INFO , REDIRECT_URL 三个系统$_SERVER变量的
判断处理来兼容读取$_SERVER['PATH_INFO'],如果你的主机环境有更特殊的设置,可以修改URL_PATHINFO_FETCH参数,改成你的环境配置对应的PATH_INFO的系统变量兼容获取名称。
我在之前也提过,在apache环境跟nginx环境通过
var_dump($_SERVER['PATH_INFO']);
打印出来的结果不相同,但这并不表示nginx环境中的$_SERVER数组,不包含apache环境中$_SERVER['PATH_INFO']的值。有兴趣的,可以自己在不同的环境中执行以下代码,看看自己的环境,支持哪个变量。
print_r($_SERVER);
我来说两句: