ThinkPHP在Nginx下404主因是请求未进入框架,需先验证是否被Nginx截断:访问/index.php/route/test,若返回原生404且无X-Powered-By头,则需检查Nginx伪静态规则、SCRIPT_FILENAME参数、root指向public目录等配置。

ThinkPHP在Nginx下访问控制器返回404,绝大多数情况不是代码写错了,而是请求压根没进框架——Nginx直接按路径找文件,找不到就甩个原生404,index.php根本没执行。先确认这点,再往下调。
第一步:验证是否进入ThinkPHP
访问 http://你的域名/index.php/route/test(确保这个路由没定义):
- 看到 ThinkPHP 调试页提示「找不到路由」→ 框架已接管,问题在路由注册或匹配环节
- 返回 Nginx/Apache 原生 404 页面,且响应头里没有
X-Powered-By: ThinkPHP→ 请求被 Web 服务器截断,停在这里查配置
用 curl -I http://你的域名/user/list 看响应头:只有 Server: nginx,没有 ThinkPHP 相关标识,说明 PHP 层完全没跑。
Nginx伪静态规则必须配对生效
TP6 默认走 PATH_INFO 模式(如 /index.php/user/profile),Nginx 不开重写就当真实路径查,当然 404。两种主流写法任选其一,但要配全:
立即学习“PHP免费学习笔记(深入)”;
-
推荐 try_files 方式(更规范):在
location /块里加try_files $uri $uri/ /index.php?$query_string;
注意:结尾必须带$query_string,否则$_GET为空;不能写成/index.php?s=$1(那是 TP5 写法,TP8 不认) -
if + rewrite 方式(宝塔等面板友好):
if (!-e $request_filename) {<br> rewrite ^(.*)$ /index.php?s=$1 last;<br>}
确保放在location /内,且last后不要跟break(冲突)
关键参数不能漏,尤其是 SCRIPT_FILENAME
在处理 PHP 的 location ~ \.php$ 块里,必须包含:
-
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;(强烈推荐)
或fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
绝不能用$request_filename—— 重写后它可能指向错误路径,导致 PHP 解析失败 - 如果用了
fastcgi_split_path_info,必须配套加:fastcgi_param PATH_INFO $fastcgi_path_info;
否则 TP6 拿不到$_SERVER['PATH_INFO'],路由段全丢 -
root指令必须指向public/目录,例如:root /var/www/myapp/public;
指向项目根目录或public/index.php都会出错
其他高频踩坑点
这些细节不显眼,但一碰就 404:
- 运行
php think route:list,输出为空?在app/route/app.php第一行加die('loaded');,刷新页面没中断 → 该文件根本没加载,检查多应用路径(如app/xxx/route/app.php)、APP_ENV是否匹配、url_route_on是否为true - 开启调试模式但看不到报错?检查 Nginx 配置里有没有
error_page 404 /404.html;,注释掉它,让 TP 的错误信息透出来 - TP6.0.0~6.0.7 存在路由解析 Bug,升级到 6.0.8+ 可解决一批莫名 404
- Windows 下用宝塔或 phpEnv,常见是 PHP 配置块里有
try_files $uri =404;这行,把它注释掉即可



















