Nginx 的 location ~ \.php$ 块必须独立存在于 server 级别,正确配置 fastcgi_pass、SCRIPT_FILENAME 和 PATH_INFO,否则将导致 PHP 文件下载、502、500 或路由失效等问题。

location ~ .php$ 块必须存在且位置正确
没有这个块,Nginx 就不会把 .php 请求转发给 PHP-FPM,浏览器会直接下载 PHP 文件或返回 404。它不能放在 location / 内部,也不能写成 location ^~ .php$(前缀匹配不适用)——必须用正则匹配形式。
常见错误现象:访问 http://localhost/info.php 显示源码、空白页、或 502 Bad Gateway。
- 确保该块在
server块一级,与location /并列 - 检查是否重复定义了多个
location ~ .php$,Nginx 只会生效最后一个 - 若使用自定义 root 路径(如
root /var/www/myapp;),SCRIPT_FILENAME必须能拼出真实文件路径,否则报 500 或 “No input file specified”
fastcgi_pass 必须与 php-fpm.sock 路径或端口严格一致
fastcgi_pass 的值不是固定写法,它取决于你的 PHP-FPM 实际监听方式。Ubuntu/Debian 系统通常走 Unix socket(如 unix:/run/php/php8.1-fpm.sock),CentOS/RHEL 多用 127.0.0.1:9000;Windows 下 Nginx + PHP-CGI 则必须用 127.0.0.1:9000,不能用 socket。
容易踩的坑:
立即学习“PHP免费学习笔记(深入)”;
- PHP-FPM 配置里
listen = /var/run/php/php8.1-fpm.sock,但 Nginx 写成了/run/php/php8.1-fpm.sock(少了一级目录)→ 报错connect() to unix:/run/php/php8.1-fpm.sock failed (2: No such file or directory) - PHP-FPM 运行用户(如
www-data)对 socket 文件无读写权限 → 502 - Windows 下忘记启动
php-cgi.exe -b 127.0.0.1:9000,只配了 Nginx → 502
PATH_INFO 支持需显式开启(ThinkPHP/Laravel 路由依赖)
默认配置下,index.php/abc 这类带 PATH_INFO 的 URL 会被当成静态路径处理,导致 Laravel 或 ThinkPHP 的路由失效。这不是 bug,是 Nginx 默认不拆分 SCRIPT_NAME 和 PATH_INFO。
解决方法是在 location ~ .php$ 块内添加两行:
fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info;
注意:fastcgi_split_path_info 是正则表达式,必须和实际 URL 结构匹配;如果用了 try_files fallback 方式(如 Laravel 推荐写法),这行可省略,但 SCRIPT_FILENAME 必须仍指向 index.php。
try_files + fastcgi_param SCRIPT_FILENAME 是更健壮的组合
相比老旧的 if (!-f $request_filename) { rewrite ... },现代 PHP 框架推荐用 try_files 做入口统一 fallback,避免 if 性能问题和重写陷阱。
典型写法:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
关键点:
-
$document_root$fastcgi_script_name中的$document_root必须和当前server块的root一致,否则SCRIPT_FILENAME指向错误路径 - 不要漏掉
include fastcgi_params;,它提供了基础的 FastCGI 参数(如CONTENT_TYPE、REQUEST_METHOD) - Windows 下
$document_root若含盘符(如D:/www),需确保路径分隔符为正斜杠,且 PHP 能识别该路径
location 块本质是 URI 匹配引擎,不是“只要写了就能跑”。PATH_INFO、socket 权限、$document_root 动态拼接这些细节,往往比语法本身更容易出问题。



















