调整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);

    评论:

    1. 暂无评论...
    2. 我来说两句:

        切换  

      磨途歌检测发现,您当前使用的浏览器版本过低,要想使用画板模式,请先更新浏览器

        切换  

      磨途歌随机验证码