Nginx(PHP/fastcgi)fastcgi_param 参数配置解决PATH_INFO问题

FastCGI配置
ThinkPHP项目的配置
nginx+php使用PHP_VALUE open_basedir限制站点目录防止跨站

最近在用thinkphp做一个项目,基本完成后部署到nginx服务器上才发觉nginx是不支持pathinfo的, 我们用thinkphp,CodeIgniter框架的时候,地址基本都是IP/index.ph/group_controller?***的模式。

在框架路由规则不变下, 需要使用一定正则和重定向规则来协助框架处理nginx的请求。
以下为示例解析和说明:

#访问路径的文件不存在则重写URL转交给ThinkPHP处理
if (!-e $request_filename) {
        rewrite ^/(.+?\.php)/?(.*)$ /$1/$2 last;
        rewrite ^/(.*)$ /index.php/$1 last;
}

    location ~ \.php($|/){
        fastcgi_index   index.php;
        fastcgi_pass    127.0.0.1:9000;
        include         fastcgi_params;
          
                 //---- 定义变量 $real_script_name,用于存放真实地址
        set $real_script_name $fastcgi_script_name;
        if ($real_script_name ~ "^(.+?\.php)(/.+)$") {
                 //---- 将文件地址赋值给变量 $real_script_name, 至于参数使用fastcgi_split_path_info 处理
            set $real_script_name $1;
        }
               //---- 通过split正则获取可自定义变量 并设置
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        fastcgi_param   PATH_INFO               $fastcgi_path_info;
  
        fastcgi_param   SCRIPT_NAME             $real_script_name;
        fastcgi_param   SCRIPT_FILENAME         $document_root$real_script_name;
                //---- open_basedir限制站点目录防止跨站
        fastcgi_param   PHP_VALUE               open_basedir=$document_root:/tmp/:/proc/;
                //---- 指定该域名网站的特定日志输出地址。
        access_log      /home/wwwlog/domain_access.log    access;
        error_log       /home/wwwlog/domain_error.log     error;
    }

注意TP与PATH_INFO传递问题

ThinkPHP为什么总是踩坑?因为我们都会通过重写来隐藏index.php文件,而ThinkPHP的教程,默认教的是旧版Nginx写法,且TP3.2中 URL_MODE必须设置为3也说得很隐晦(URL_MODE默认为0)。

例如ThinkPHP的说明有一段旧版的Nginx设置指引。

 location / { // …..省略部分代码
   if (!-e $request_filename) {
   rewrite  ^(.*)$  /index.php?s=$1  last;
   break;
    }
 }

该规则是通过将请求rewrite给/index.php?s=来实现的,其ThinkPHP的URL_MODE配置必须为3,也就是兼容模式。
如果使用本文中的传递PATH_INFO方式,且隐藏index.php,则ThinkPHP的URL_MODE需要改为2。
如果使用本文中的传递PATH_INFO方式,但不隐藏index.php,则ThinkPHP的URL_MODE改为1。

fastcgi_param 各参数的意义

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;#脚本文件请求的路径  
fastcgi_param  QUERY_STRING       $query_string; #请求的参数;如?app=123  
fastcgi_param  REQUEST_METHOD     $request_method; #请求的动作(GET,POST)  
fastcgi_param  CONTENT_TYPE       $content_type; #请求头中的Content-Type字段  
fastcgi_param  CONTENT_LENGTH     $content_length; #请求头中的Content-length字段。  
  
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name; #脚本名称   
fastcgi_param  REQUEST_URI        $request_uri; #请求的地址不带参数  
fastcgi_param  DOCUMENT_URI       $document_uri; #与$uri相同。   
fastcgi_param  DOCUMENT_ROOT      $document_root; #网站的根目录。在server配置中root指令中指定的值   
fastcgi_param  SERVER_PROTOCOL    $server_protocol; #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。    
  
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;#cgi 版本  
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;#nginx 版本号,可修改、隐藏  
  
fastcgi_param  REMOTE_ADDR        $remote_addr; #客户端IP  
fastcgi_param  REMOTE_PORT        $remote_port; #客户端端口  
fastcgi_param  SERVER_ADDR        $server_addr; #服务器IP地址  
fastcgi_param  SERVER_PORT        $server_port; #服务器端口  
fastcgi_param  SERVER_NAME        $server_name; #服务器名,域名在server配置中指定的server_name  
  
#fastcgi_param  PATH_INFO           $path_info;#可自定义变量  
  
# PHP only, required if PHP was built with --enable-force-cgi-redirect  
#fastcgi_param  REDIRECT_STATUS    200;  

推荐阅读更多精彩内容