显示目录
常见问题FAQ 系统配置

配置Nginx支持path_info

默认情况下,nginx是不支持path_info的,我们需要做些配置让它支持。

找到ngingx的配置文件nginx.conf,在server里的location项

location ~ \.php(.*)$ {
        root           /var/www/nginx/html;
        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_split_path_info  ^(.+\.php)(.*)$;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO $fastcgi_path_info;
        include fastcgi_params;
    }


备注:

1. ~ \.php改为~ \.php(.*),因为要接收.php后面的参数,不能让它被当做目录处理。

2. 添加fastcgi_split_path_info,该参数后面需指定正则表达式,而且必须要有两个捕获,第一个捕获将会重新赋值给$fastcgi_script_name,第二个捕获将会重新赋值给$fastcgi_path_info。

3. 添加fastcgi_param PATH_INFO,值为$fastcgi_path_info。



下面是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://csdeshang.com/index.php/Article/Post/index.html,这种Url可以理解为:


index.php当做一个目录看待:访问csdeshang.com服务器根目录下的index.php目录下的Article目录下的Post目录下的index.html静态html文本文件;

index.php当做一个PHP脚本看待:访问csdeshang.com服务器根目录下的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;

}