ThinkPHP 6.0伪静态404主因是请求未进入框架,核心在于运行目录未设为/public、伪静态规则不匹配TP6的PATH_INFO模式、Nginx未透传fastcgi_param PATH_INFO。

ThinkPHP 6.0 开启伪静态后出现 404,绝大多数情况不是代码写错了,而是请求压根没进到框架里——Web 服务器直接拦截并返回了原生 404。核心问题集中在三处:运行目录不对、伪静态规则不匹配 TP6 结构、PATH_INFO 没传给 PHP。
运行目录必须设为 /public
TP6 默认把入口文件 index.php 放在 public/ 子目录下,但宝塔或 PHPStudy 新建站点时,默认根目录是指向项目顶层(如 /www/wwwroot/myapp),不是 /www/wwwroot/myapp/public。结果 Nginx 去错地方找 index.php,自然 404。
- 宝塔:网站 → 设置 → 网站目录 → 运行目录,选择
/public(注意开头有斜杠) - PHPStudy:站点管理 → 网站根目录,手动改为指向
your-project/public - 改完务必点「保存」+「重载 Web 服务」,只保存不重载等于没改
- 验证方式:访问
/index.php应该 404;访问/public/index.php或直接打开域名能显示首页
伪静态规则不能套用 TP5 模板
宝塔面板里下拉选“ThinkPHP”是为 TP5 设计的(走 index.php?s=/xxx),而 TP6 默认用 PATH_INFO 模式(/user/list),且入口在 public 下。直接套用会导致 rewrite 目标变成 /index.php(404),而不是 /public/index.php。
- 清空宝塔「伪静态」文本框,粘贴以下内容(注意位置:要放在
location ~ \.php$块之前):
rewrite ^(.*)$ /index.php/$1 last;
}
- 如果站点根目录仍指向项目顶层(未设为 /public),则改用:
if(!-e $request_filename) {
rewrite ^(.*)$ /public/index.php/$1 last;
} - 必须用 last,不是 break 或 redirect;只有 last 会触发重新匹配 location,让请求真正落到 PHP 处理块
- 改完后进 SSH 执行
nginx -t && systemctl reload nginx,别只信宝塔界面上的“重载”
确保 PATH_INFO 正确传递给 PHP
TP6 路由依赖 $_SERVER['PATH_INFO'] 解析路径段(如 /user/list)。Nginx 默认不传这个变量,需在 PHP-FPM 配置中显式声明。
立即学习“PHP免费学习笔记(深入)”;
- 检查 Nginx 配置中
location ~ \.php$块内是否有这两行:
fastcgi_param PATH_INFO $fastcgi_path_info;
- 同时确认 php.ini 中
cgi.fix_pathinfo = 1已开启,改完重启 php-fpm - 禁用函数也要检查:宝塔 → PHP 设置 → 禁用函数,删掉
scandir、putenv、ini_set(TP6 启动时要用) - 调试小技巧:在入口文件
public/index.php开头加一行var_dump($_SERVER['PATH_INFO'], $_SERVER['REQUEST_URI']);,看是否拿到真实路径
顺手排查几个高频漏点
-
.htaccess 不起作用? Apache 用户请确认虚拟主机配置中
AllowOverride All已启用,不是None -
路由缓存没清? 删除
runtime/cache/和runtime/route/下所有文件 -
强制路由开启? 若配置了
'url_route_must' => true,静态资源(如 CSS/JS/图片)也会被拦截 404,记得加白名单或临时关掉测试 -
URL 对比法验证:如果
/user/list404,但/index.php/user/list能打开,就是伪静态完全没生效的铁证



















