根本原因是nginx未正确转发请求给php-fpm:alias配置下$document_root失效,导致script_filename路径拼错;fastcgi_pass地址不匹配、php.ini中cgi.fix_pathinfo=1未关闭、或多个location ~ \.php$块冲突也会引发下载。

访问 Nginx 下的 phpMyAdmin 时直接下载 index.php,根本原因不是 phpMyAdmin 本身有问题,而是 Nginx 无法将请求正确转发给 PHP-FPM 处理——它把 .php 文件当成了静态资源返回,浏览器收到原始文件内容后触发了默认下载行为。
location 配置用了 alias 却没适配 SCRIPT_FILENAME
这是最常见也最容易被忽略的坑。用 alias 指向 phpMyAdmin 目录(比如 alias /usr/share/phpmyadmin/;)后,$document_root 变量就失效了——它仍指向 root 定义的主站根目录,而不是 alias 实际映射的路径。
结果是:fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 拼出来的路径根本不存在,PHP-FPM 找不到文件,Nginx 回退到直接返回原始 PHP 文件内容。
解决方法只能手动拼对路径:
- 删掉所有依赖
$document_root的SCRIPT_FILENAME行 - 在
location块里显式写死路径,例如:fastcgi_param SCRIPT_FILENAME /usr/share/phpmyadmin/$fastcgi_script_name; - 确保该路径与
alias后的值完全一致(注意末尾斜杠、大小写、软链接是否已解析)
fastcgi_pass 地址不匹配或 PHP-FPM 未运行
即使 location 写对了,如果 fastcgi_pass 指向一个没监听的地址,Nginx 会静默失败并返回原始文件——不会报 502,也不会写 error log(除非开启 error_log ... notice;)。
检查要点:
- 运行
sudo systemctl status php-fpm或ps aux | grep php-fpm,确认服务在运行 - 看 PHP-FPM 配置里的
listen =值,是127.0.0.1:9000还是unix:/run/php/php8.2-fpm.sock?Nginx 的fastcgi_pass必须严格一致 - Docker 环境下注意网络连通性:
fastcgi_pass php:9000要求 nginx 容器能 DNS 解析到 php 容器,且端口开放
php.ini 中 cgi.fix_pathinfo 设为 1
这个配置项看似无关,实则致命。当设为 1 时,PHP-FPM 会尝试“聪明地”解析 PATH_INFO,容易把 /mysql/index.php/some/path 这类请求误判为非法,然后拒绝处理,Nginx 接着回退到静态响应。
必须改为:
cgi.fix_pathinfo=0
改完后重启 PHP-FPM(不是 reload),否则不生效。很多一键包(如宝塔、AMH)默认开这个,就是为 phpMyAdmin 埋雷。
多个 location ~ \.php$ 块冲突
有人为了兼容别名路径,额外加了一个 location ~ /mysql/.+\.php$,但又保留了全局的 location ~ \.php$。Nginx 匹配 location 是按最长前缀 + 正则优先级来的,两个规则可能互相覆盖,导致部分 PHP 请求走错流程。
建议只留一个精准匹配块,并用 ^~ 或 = 提升别名路径的优先级:
- 用
location ^~ /mysql/匹配别名前缀 - 里面嵌套
location ~ \.php$,且不带其他正则干扰 - 删掉全局的、宽泛的
location ~ \.php$,避免兜底干扰
复杂点在于:phpMyAdmin 内部有大量重写和子请求(比如 /mysql/js/xxx.js.php),PATH_INFO 和 SCRIPT_NAME 的边界稍有偏差,就会触发下载。这种问题往往要结合 curl -I 看响应头、tail -f /var/log/nginx/error.log 看实际转发路径,才能定位到哪一行参数没对上。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











