thinkphp在nginx下跑不起来的主因是nginx配置错误:root未指向public目录、try_files规则误用if判断、fastcgi_pass与script_filename路径不匹配、path_info模式未适配或冗余启用。

try_files 写错、fastcgi_pass 指向失效、或 SCRIPT_FILENAME 拼出的路径根本不存在。
ThinkPHP 入口文件必须被正确路由到 public/index.php
ThinkPHP 5/6/8 默认使用 public 目录为 Web 根目录,index.php 是唯一入口。Nginx 的 root 必须指向项目 public 目录,而不是项目根目录:
-
root /var/www/myapp/public;✅ 正确(index.php可被直接访问) -
root /var/www/myapp;❌ 错误(/public/index.php变成内部路径,Nginx 找不到)
如果你硬要 root 到项目根目录,就得用 alias,但极易出错,不推荐。
try_files 替代 if (!-e $request_filename)
网上大量教程还在用 if 判断文件是否存在再 rewrite,这在 Nginx 里是反模式,容易引发重写循环或静默失败。正确做法是用 try_files:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
这条规则含义清晰:先找静态文件,再找目录,最后兜底到 index.php 并透传查询参数。注意三点:
- 末尾是
/index.php?$query_string,不是/index.php/$1—— ThinkPHP 8 默认用 querystring 模式,不是 PATH_INFO - 如果项目强制启用 PATH_INFO(如旧版 TP3.2),才需要额外配置
fastcgi_split_path_info和PATH_INFO参数 -
try_files必须放在location /块里,不能丢进location ~ \.php$里
fastcgi_pass 和 SCRIPT_FILENAME 必须严丝合缝
这是最常卡住部署的环节。PHP 请求能否进 php-fpm,全看这两项是否匹配:
-
fastcgi_pass要和 php-fpm 实际监听方式一致:
– Unix socket:fastcgi_pass unix:/run/php/php8.1-fpm.sock;(注意unix:前缀不能少)
– TCP:fastcgi_pass 127.0.0.1:9000;(别写localhost,DNS 解析可能拖慢或失败) -
fastcgi_param SCRIPT_FILENAME必须拼出真实绝对路径:
– 推荐用$realpath_root$fastcgi_script_name(自动解析软链,更健壮)
– 若用$document_root$fastcgi_script_name,请确认root已正确定义且无拼写错误 - 漏掉
fastcgi_param QUERY_STRING $query_string;会导致路由参数丢失,$_GET为空
调试时可在 PHP 中打印 $_SERVER['SCRIPT_FILENAME'],看它是否真指向 /var/www/myapp/public/index.php。
PATH_INFO 模式需额外启用且易踩坑
ThinkPHP 默认已弃用 PATH_INFO(TP6+ 默认关闭,TP8 强制 querystring),但若你继承老项目或手动开启,Nginx 必须显式支持:
- 在
location ~ \.php($|/)块中加:fastcgi_split_path_info ^(.+\.php)(/.+)$;fastcgi_param PATH_INFO $fastcgi_path_info; -
fastcgi_param SCRIPT_FILENAME仍需保留,且值不能含 PATH_INFO 部分 - PATH_INFO 模式下,URL 如
/index.php/user/index才有效;而 querystring 模式下,等价 URL 是/index.php?s=/user/index - 很多云主机或容器环境禁用 PATH_INFO,优先走 querystring 模式更稳妥
PATH_INFO 不是“更高级”,只是历史兼容方案;现代部署应默认关闭它,避免多一层解析风险。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











