为什么 TP6.0 路由定义不生效:缓存清理与规则冲突排查:路由

作者:袖梨 2026-07-21
TP6.0路由404主因是APP_DEBUG未关闭导致缓存失效;需确认config/app.php中'app_debug'=>false,清空runtime/route/并执行php think route:cache --annotation;动态路由须置于app/route.php顶层或用Route::import,避免写在运行时逻辑中。

路由定义写了但 404,先看 APP_DEBUG 是否真关闭

TP6.0 路由缓存只在 APP_DEBUG=false 时生效;只要 thinkApp::debug() 返回 true,哪怕你刚生成了 runtime/route.php,框架也会跳过缓存、重新解析所有路由文件——此时你改了 route/app.php 却没生效,大概率是调试模式还开着。

检查方式:在任意控制器里加 dump(thinkApp::debug());,输出 true 就说明没关掉。注意:.env 中设 APP_DEBUG=false 不保险,最终以 config/app.php 里的 'app_debug' => false 为准。CI/CD 构建后若漏改此项,上线即失效。

执行 php think route:cache 前没清旧缓存或漏参数

缓存命令不会自动覆盖或清理旧文件,runtime/route/ 目录残留空文件、损坏数组或旧版本内容,会导致新路由不载入。同时,注解路由(@Route)默认不扫描,必须显式加 --annotation 参数,否则 route:cache 只处理 route/app.php 这类 PHP 文件。

  • 执行前手动清空:rm -rf runtime/route/
  • 带注解必须用:php think route:cache --annotation
  • 注解只识别 app/controller/ 下的类,命名空间错位、文件名大小写不符(Linux 敏感)、use 别名引入都会导致漏扫
  • PHP 8 Attributes(如 #[Route])在 TP 6.0.x 中不支持缓存,得降级为 PHPDoc 注解

动态路由写在错误位置,缓存阶段根本没执行

Route::rule() 或从数据库读取的动态路由,如果写在控制器方法、事件监听器、闭包里,route:cache 命令运行时根本不会执行它——缓存只序列化静态结构,不跑运行时逻辑。

正确做法是把动态路由注册逻辑提到 app/route.php 文件顶层,确保命令执行时能立即执行并返回完整路由数组。或者改用 Route::import('path/to/dynamic_routes.php'),该 PHP 文件可含简单逻辑(如读 JSON),但禁止 DB 查询、HTTP 请求等阻塞操作。

验证是否进缓存:运行 php think route:list,输出里没你的动态路由,说明缓存阶段就没注册进去。

路由规则被前置 permit ip any any 或伪静态干扰

多应用模式下,访问 /admin/getlog 必须带上模块名,即实际路径是 /index.php/admin/getlog;若没配伪静态,直接访问会 404。另外,部分用户误将 ACL 思维套到路由上:比如在 route/app.php 顶部写了 Route::any('/', function () { return 'home'; });,后面所有规则都匹配不到——因为 any 通配优先级最高。

常见干扰点:

  • 没启用伪静态时,浏览器地址栏必须带 index.php,例如 http://hml.tp6.com/index.php/admin/getlog
  • 新增路由是 POST,但在浏览器地址栏用 GET 访问,必然 404(可用 Apipost 测试)
  • 路由定义顺序影响匹配,Route::get('user/:id', ...) 要放在更宽泛的规则(如 Route::get('user/*', ...))之前

真正难排查的,是缓存文件存在但内容为空、或被旧逻辑污染——这时候 route:list 看不到任何路由,连基础 / 都 404,得盯住 runtime/route.php 文件本身是否可读、是否真包含有效数组。

相关文章

精彩推荐