404 错误通常源于 Web 服务器未将请求交由 ThinkPHP 处理,或路由文件未加载、环境未就绪;需检查 Nginx 重写规则、路由定义位置、大小写敏感性及静态资源拦截问题。

404 不是路由写错了,而是请求根本没进到 ThinkPHP 的路由系统里——绝大多数情况,问题出在 Web 服务器配置或框架初始化时机上。
为什么 php think route:list 不显示你的路由
这个命令只输出「已成功加载并注册」的路由。如果它不显示,说明路由文件压根没被执行,或者执行时框架环境还没就绪。
- 检查
route/app.php是否真被加载:在文件开头加die('route loaded');,访问任意 URL 看是否中断;没中断=该文件根本没运行 - 别在控制器、模型或中间件里调用
Route::get()—— 此时think\facade\Route尚未初始化,调用无效且无报错 - 确认
config/app.php中'url_route_on' => true已启用,且没被环境变量(如.env)覆盖 - 如果你用了多应用模式,确保路由定义在对应应用的
route/app.php,而不是根目录下的route/route.php
Nginx 下 /user/list 404,但 /index.php/user/list 正常
这是典型的重写规则缺失或错误,Nginx 没把请求交给 index.php,而是直接去文件系统找 /user/list 这个路径,当然 404。
- 必须确保
location /块里有这行:try_files $uri $uri/ /index.php?$query_string;—— 缺少$query_string会导致?id=123参数丢失,$_GET为空 -
fastcgi_param SCRIPT_FILENAME必须写成$document_root$fastcgi_script_name,不能用$request_filename,后者在重写后可能指向错误路径 - 子目录部署(如
https://site.com/app/)时,location要匹配前缀:location /app/ { try_files $uri $uri/ /app/index.php?$query_string; },且rewrite规则要剥离前缀再传给 PHP - 宝塔等面板选了 “ThinkPHP” 伪静态,仍需手动打开配置文件,确认生成的规则确实存在且已重载 Nginx
开启 'url_route_must' => true 后 /static/css/app.css 404
强制路由会拦截所有请求,包括静态资源。它不会自动识别 .css、.js 是文件,而是当成需要匹配的动态路由,找不到就 404。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
立即学习“PHP免费学习笔记(深入)”;
- 最稳方案:用
Route::rule()显式放行带扩展名的请求,放在route/app.php最顶部:Route::rule(':path^.*\.(js|css|png|jpg|gif|svg|woff2|ttf)$', 'static/:path', 'GET', ['ext' => '']); -
['ext' => '']关键:禁用 ThinkPHP 自动补全后缀(否则/a.js可能被当成/a.js.html匹配失败) - 别依赖
Route::alias('static', 'static')—— 它隐含假设静态资源都在public/static/,CDN 或动静分离部署时失效 - 同时检查 Nginx 层有没有冲突的
location ~* \.(js|css)$规则,它会绕过 PHP 直接返回 404,导致你的路由规则完全不生效
Linux 上大小写敏感引发的 404
Windows 开发时一切正常,一上 Linux 就挂,大概率是 URL 路径或控制器名大小写不一致。ThinkPHP 默认区分大小写,而 Windows 文件系统不区分,掩盖了问题。
- 前端请求的 URL(如
/User/List)必须和Route::get('/user/list', ...)中的路径**逐字符一致**,包括开头斜杠、大小写、下划线 - 控制器类名(如
UserController)和方法名(如list)也要严格匹配:Linux 下User.php≠user.php,list()≠List() - 不要为图省事开
'url_convert' => true自动转小写——它会让/USER/LIST也匹配成功,掩盖命名混乱,后期维护更难 - CI/CD 流程中加入大小写校验脚本,比如用
find . -name "*[A-Z]*.php"扫描非法大写文件名
真正卡住人的不是某条路由怎么写,而是你不确定请求到底被谁处理了:是 Nginx 直接 404?还是进了 PHP 但没加载路由文件?还是路由加载了但没匹配上?先跑一遍 php think route:list,再看浏览器 Network 面板的状态码和响应头里的 X-Powered-By,比反复改代码更快定位问题源头。


















