转自 Nginx 与 PHP 的正确使用姿势 ( 以及 PATH_INFO ) – Snow Star 博客
通常来说, PHP 和 nginx 一块用的时候, PHP 通过 php-fpm 启动处理进程, nginx 通过 fastcgi 协议和 fpm 进行通信.
也就是当客户端请求 .php 的时候, nginx 通过正则匹配文件, 然后设置一些重要的变量, 比如 SCRIPT_FILENAME 这些变量, 然后反向代理给监听的 fpm 处理, 当 fpm 处理完 php 脚本之后将结果返回给 nginx.
因此对于一般的 php 程序来说, nginx 配置文件只需要简单的加如下内容
location ~* \.php$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
在这里通过 fastcgi_pass 指定 fpm 监听的地址, 而 include fastcgi_params 来包含一个预先定义好的文件, 此文件中通过一系列的 fastcgi_param 指令设置了一大堆 CGI 1.1 协议当中的变量, 这些变量将会在 $_SERVER 魔术变量当中可以获取到.
虽然此方法可以让一般的 php 程序正常运行, 但这会让一些基于 PATH_INFO 来运行的程序产生404, 例如 wordpress 等
要想解决这个问题, 首先得明白什么是 PATH_INFO, 你去百度搜索一下, 几乎所有人都会跟你说:
PATH_INFO 不是 nginx 的功能, 是 PHP 的功能
对此我只能说, fnndp, PATH_INFO 的确不是 nginx 的功能, 但它也不是 PHP 的功能, 相反, PATH_INFO 是 CGI 1.1 协议当中定义的 Request Meta-Variables, 具体可以查阅RFC 3875 的 4.1.5 小节.
而一些 PHP 框架大量运用这一特性进行 URL 美化, 例如 /index.php/this/is/path/info
这间接导致了几乎让一大堆人认为 PATH_INFO 就是 PHP 的功能.
知道了什么是 PATH_INFO 之后, 该怎么解决呢? 通常有两种办法.
使用 php 的 cgi.fix_pathinfo 功能 [deprecated]
强烈不推荐此种方式
此方式通过将 php.ini 当中的 cgi.fix_pathinfo 设置为1, 并且在 nginx 中加入一条 fastcgi_param PATH_INFO $fastcgi_script_name;
当开启 fix_pathinfo 之后, php 会根据 CGI 1.1 的规范来分析 SCRIPT_FILENAME, 从中截取什么是真正的执行脚本, 什么是 PATH_INFO, 并且修正对应的变量
但这种方法有严重的安全隐患, 会引起脚本注入. 因此强烈不推荐用这种方式, 如果有人教你说用这种方式, 请赶快修正你的配置.
使用 nginx 的 fastcgi_split_path_info 功能
此种方式依赖 nginx 的 fastcgi_split_path_info 指令, 该指令通过正则表达式来对 uri 进行处理, 从中分理出真实脚本文件和 PATH_INFO, 并根据正则捕获组来设置两个重要变量
1. $fastcgi_script_name
2. $fastcgi_path_info
当使用这种方式的时候, nginx 的配置看起来如下
location ~ ^(.+\.php)(.*)$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
需要注意的是第一行修改了原来的正则, 同时第七行增加了 fastcgi_split_path_info 指令, 而第九行的值改为了正确的 $fastcgi_path_info.
同时需要注意将 cgi.fix_pathinfo 设置为0.
通过对 nginx 进行调整之后就可以正确的使用 PHP 功能了.