真 · nginx配置php文件解析(PATH_INFO支持与index.php隐藏)

nginx默认配置文件中对php的支持是这样的:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html; # html改成项目路径
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # html改成项目路径 # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
#    root           html;            # html改成项目路径
#    fastcgi_pass   127.0.0.1:9000;
#    fastcgi_index  index.php;
#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
#    include        fastcgi_params;
#}

nginx对php的处理原则是将匹配到的以.php结尾的文件转交给FastCGI服务进程(FastCGI是一种协议,php-fpm是实现了FastCGI协议的程序)。

但只启用这个配置是不够的,首先,他无法处理PATH_INFO信息。即在php文件中使用全局变量$_SERVER[‘PATH_INFO’]只能得到空值。另外,他只能处理http://domain/index.php/controller/action?query_string这样的url,无法隐藏index.php。对于现在的web框架来说,将index.php文件作为php的单一入口,并在url上隐藏index.php是最基本的要求。有些框架还可能需要用到PATH_INFO来实现路由转发。

网上有好多资料讲怎么配置nginx来实现PATH_INFO支持与index.php隐藏的,但试了好多都是不完善的,要么支持了$_SERVER[‘PATH_INFO’]但不支持隐藏index.php,要么是无法获取$_SERVER[‘QUERY_STRING’]。就连我去年一直用到现在的配置其实也是有问题的。

今天试了好久,总算确定了一个最合理的配置:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
server {
listen 80;
server_name your_domain;
location / {
root your_code_path;
index index.html index.htm index.php;
# 无法找到的文件路径交给index.php处理
# $args变量表示查询字符串,将其传递给index.php,否则index.php无法获取QUERY_STRING
try_files $uri $uri/ /index.php$is_args$args;
}
# 匹配.php文件
location ~ [^/]\.php(/|$) {
# 从请求路径中匹配出$fastcgi_script_name与$fastcgi_path_info两个变量
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# 如果.php文件不存在,返回404
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
root your_code_path;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
server { listen 80; server_name your_domain; location / { root your_code_path; index index.html index.htm index.php; # 无法找到的文件路径交给index.php处理 # $args变量表示查询字符串,将其传递给index.php,否则index.php无法获取QUERY_STRING try_files $uri $uri/ /index.php$is_args$args; } # 匹配.php文件 location ~ [^/]\.php(/|$) { # 从请求路径中匹配出$fastcgi_script_name与$fastcgi_path_info两个变量 fastcgi_split_path_info ^(.+?\.php)(/.*)$; # 如果.php文件不存在,返回404 if (!-f $document_root$fastcgi_script_name) { return 404; } root your_code_path; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }
server {
    listen       80;
    server_name  your_domain;

    location / {
        root   your_code_path;
        index  index.html index.htm index.php;

        # 无法找到的文件路径交给index.php处理
        # $args变量表示查询字符串,将其传递给index.php,否则index.php无法获取QUERY_STRING
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # 匹配.php文件
    location ~ [^/]\.php(/|$) {

        # 从请求路径中匹配出$fastcgi_script_name与$fastcgi_path_info两个变量
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;

        # 如果.php文件不存在,返回404
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }

        root         your_code_path;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;

        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO        $fastcgi_path_info;
    }
}

当然你也可以将后面两句fastcig_param写到/etc/nginx/fastcig_params文件中。

参考:

https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/

 

@2020.05

DigitalOcean 出了一个可视化的 nginx 配置工具 nginxconfig.io,还是很好用的。

参考:https://www.hawu.me/operation/2129#5_nginx

 

Leave a Comment

Your email address will not be published. Required fields are marked *