thinkphp伪静态404根本原因是web服务器未将请求转发至index.php,而非框架本身错误;需检查apache的mod_rewrite、allowoverride及.htaccess,或nginx的try_files、path_info传递、运行目录配置,并用curl -i确认404来源层级。

ThinkPHP 伪静态 404 不是框架问题,而是请求根本没进 PHP —— 你看到的 404 来自 Nginx 或 Apache,不是 ThinkPHP 抛的。
为什么 /user/list 直接 404,但 /index.php/user/list 能通
这是最典型的症状:Web 服务器没把请求转发给 index.php。它在文件系统里找 /user/list 这个路径,当然找不到,直接返回 404。ThinkPHP 根本没机会执行。
- Apache 用户:检查
.htaccess是否存在、mod_rewrite是否启用、虚拟主机是否配置AllowOverride All - Nginx 用户:确认站点配置中
location /块里有try_files $uri $uri/ /index.php?$query_string;—— 缺少$query_string会导致$_GET为空,后续路由也可能失败 - 宝塔用户:别只点“伪静态 → ThinkPHP”,要点开文本框,确认生成的规则确实是上面那行;很多版本生成的是过时的
/index.php?s=$1,TP6 默认不认这个
TP6 的 index.php 在 public 目录,但宝塔根目录设错了
TP6 默认入口是 public/index.php,而宝塔新建站点时默认把网站根目录指向项目根(即 thinkphp6/),导致 Nginx 在错误位置找 index.php。
- 进宝塔【网站】→【设置】→【网站目录】→【运行目录】,选
/public(注意开头斜杠) - 改完必须点【保存】,再对站点执行【重启】,否则配置不生效
- 验证方式:访问
/public/index.php能打开,但/index.php404,说明运行目录已生效
if (!-e $request_filename) { rewrite ... } 是过时写法,慎用
这种 if 判断在 Nginx 里性能差、语义模糊,且容易和 location ~ \.php$ 冲突,TP6 官方也不推荐。它还会绕过 try_files 的缓存逻辑,让静态资源处理变不可控。
- 正确做法是统一用
try_files:优先查真实文件/目录,查不到就交由/index.php?$query_string - 如果用了
fastcgi_split_path_info,确保它只出现在location ~ \.php$块内,不要放在location /里 - TP6 默认依赖
PATH_INFO,Nginx 必须传参:fastcgi_param PATH_INFO $fastcgi_path_info;,否则/user/list中的/user/list段不会被路由系统读到
路由定义写了但 php think route:list 不显示
命令行不输出你的路由,说明它们压根没被加载 —— 不是规则写错,是根本没注册进去。
- 检查路由是否写在
route/app.php(单应用)或route/<app_name>.php</app_name>(多应用),而不是控制器、中间件或钩子里 - 确认没有被条件包裹,比如
if (env('APP_DEBUG')) { Route::get(...); }—— 线上环境 APP_DEBUG=false,路由就消失了 - TP6 多应用下,
Route::get()默认注册到当前应用,若请求域名/路径不匹配Route::domain()或Route::group(['prefix' => 'admin']),路由也不会命中
真正难调试的从来不是哪条规则怎么写,而是你不确定请求在抵达 PHP 前被谁拦截了:是 Nginx 的 location 规则?是宝塔的运行目录?还是 Apache 的 AllowOverride?先用 curl -I http://yoursite/user/list 看响应头里的 Server 和 X-Powered-By,就能立刻区分是 Web 服务器层 404,还是 PHP 层 404。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











