Nginx配置支持PHP的PATHINFO

最近有项目用到thinkphp5.0,顺便了解下nginx关于PATHINFO的配置。

先贴最终配置文件:

set  $root "/var/www/tenshi_cc/example/public";
root $root;

location / {
    index  index.html index.htm index.php;
    ##隐藏链接中的index.php, 不加$query_string会丢失$_GET
    try_files $uri $uri/ /index.php$uri?$query_string;
}
##匹配nginx需要交给php-fpm的URI,需要先允许PATHINFO格式的url被匹配到
location ~ ^(.+\.php)(.*)$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    ##增加 fastcgi_split_path_info指令,将URI匹配成PHP脚本的URI和pathinfo两个变量
    ##即$fastcgi_script_name 和$fastcgi_path_info
    fastcgi_split_path_info ^(.+\.php)(.*)$;
    ##PHP中要能读取到pathinfo这个变量
    ##就要通过fastcgi_param指令将fastcgi_split_path_info指令匹配到的pathinfo部分赋值给PATH_INFO
    ##这样PHP中$_SERVER['PATH_INFO']才会存在值
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    ##检查这个绝对地址的PHP脚本文件是否存在
    ##如果这个PHP脚本文件不存在就不用交给php-fpm来执行了
    if (!-e $document_root$fastcgi_script_name) {
        ##此处返回404,也可以rewrite重写
        return 404;
    }
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

下面是CGI、FastCGI和PATHINFO的关系

CGI

通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

FastCGI

FastCGI的Fast已经表明含义了,是一种快速的CGI,也是现代动态网页语言与web server之间普遍所采用的。FastCGI像是一个常驻型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。它还支持分布式的运算,即FastCGI程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

nginx与php-fpm就是采用的FastCGI模式。

PATHINFO

thinkphp 5.0默认的url格式为http://tenshi.cc/index.php/Article/Post/index.html,这种Url可以理解为:

  • index.php当做一个目录看待:访问tenshi.cc服务器根目录下的index.php目录下的Article目录下的Post目录下的index.html静态html文本文件;
  • index.php当做一个PHP脚本看待:访问tenshi.cc服务器根目录下的index.php脚本,由该脚本产生html页面,Url中/Article/Post/index.html这一部分作为index.php脚本中使用的某种类型的参数。

绝大部分情况下,这种格式的Url理解方式是第二种,而/Article/Post/index.html这一部分理解成PATHINFO就好了。其实PATHINFO是一个CGI 1.1的一个标准,经常用来做为传参载体,只不过咱们没必要深入。

由于Apache的默认配置文件开启了PATHINFO的支持,Apache+PHP的环境下PATHINFO格式的Url可以不出任何错误的执行正确路径的PHP脚本并在脚本中使用PATHINFO中的参数。而Nginx默认提供的有关执行php-fpm运行PHP脚本的默认配置文件中并没有启用PATHINFO,从而导致了一个长久以来的误解:nginx不支持pathinfo。

早期版本的nginx确实不能直接支持pathinfo,但有变相的解决方法,网络上的一些配置nginx支持pathinfo的文章大多就是这种变相解决方法。nginx其实早已可以很简单的通过 fastcgi_split_path_info 指令支持pathinfo模式了,严格来说是nginx的0.7.31以上版本就可以使用这个指令了。

隐藏链接中的index.php

nginx的 try_files 按顺序检查文件的存在,并返回找到的第一个文件。在没有找到文件的情况下,调用到最后一个参数的内部重定向,只有最后一个参数会导致内部重定向。

所以可以使用 try_files 来隐藏url中的index.php

try_files $uri /index.php$uri;

也可以使用 rewrite 指令来实现相同的功能

if ( !-e $request_filename) {
    rewrite ^/(.*)$ /index.php/$1 last;
}

Copyright ©2016-2018 红世幻境 All Rights Reserved

浙ICP备15041976号-2 联系邮箱: shana@tenshi.cc

Top