路由缓存生效需同时满足运行时环境、加载时机与缓存介质三者严丝合缝:ThinkPHP要求APP_DEBUG=false、route_check_cache=true、runtime/route.php存在且可读;Laravel要求全静态路由定义、生产环境、无闭包;FastRoute需绝对路径及目录可写;OPcache须opcache.validate_timestamps=0且opcache.enable_cli=1。

路由缓存不是“开了就快”,而是必须和运行时环境、加载时机、缓存介质三者严丝合缝才能生效。单独执行php think route:cache或php artisan route:cache,但没关APP_DEBUG、没配opcache.validate_timestamps=0、没确认runtime/route.php可被 Web 进程读取——结果就是缓存文件躺在磁盘上,请求却还在逐行解析route/app.php。
ThinkPHP 路由缓存不生效的 4 个硬性前提
ThinkPHP 只在同时满足以下全部条件时才真正加载缓存文件:
-
APP_DEBUG = false(且未被.env覆盖,可用php think env:show验证) -
config/app.php中'route_check_cache' => true显式开启 -
runtime/route.php存在,且 Web 进程用户(如www-data)有读权限 - 若启用多应用模式,缓存路径需匹配当前应用名,例如
runtime/route/admin/route.php,否则框架根本找不到
Laravel route:cache 的静态路由红线
Laravel 的缓存机制只接受完全静态的路由定义,任何运行时逻辑都会导致生成失败或运行时报错:
- 闭包路由:
Route::get('/test', function () { ... });→ 报错Target class [Closure] does not exist - 条件注册:
if (config('feature.flag')) { Route::get(...); }→ 缓存阶段无法执行,直接跳过或报错 - 动态控制器字符串:
Route::get('/x', 'DynamicController@method');→ 不安全,推荐改用数组语法[DynamicController::class, 'method'] - 注解路由(
#[Route])在 Laravel 9+ 支持,但需确保doctrine/annotations已安装且cache:clear --env=prod触发了完整编译
FastRoute 缓存驱动选型与路径陷阱
FastRoute 的缓存不是“开关式”配置,而是依赖你传入的缓存路径和驱动实现是否可靠:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
立即学习“PHP免费学习笔记(深入)”;
- 使用
FastRoute::recommendedSettings($callback, $cacheFile)时,$cacheFile必须是**绝对路径**,相对路径(如'cache/route.cache')在 CLI 和 Web 环境下行为不一致,极易静默失败 -
src/Cache/FileCache.php是默认文件驱动,但它不自动创建父目录;若cache/目录不存在,缓存写入失败且无提示 - 想对接 Redis,必须用
Psr16Cache驱动,并传入符合 PSR-16 的实例(如new RedisAdapter($redis)),不能直接传$redis对象 - 缓存键(cache key)若跨项目复用(比如多个 TP 应用共用一个
route.cache路径),会导致路由规则互相污染,出现 404 或错配
OPcache + 路由缓存双失效的典型链路
ThinkPHP/Laravel 生产环境性能翻车,往往不是某一处错了,而是三层缓存中有一层没对齐:
- OPcache 层:
opcache.validate_timestamps=0和opcache.revalidate_freq=0必须**同时设为 0**,单设一个仍会触发stat()检查,拖慢首次请求 - 路由缓存层:生成后要删掉
runtime/route/整个目录再重跑命令,仅删route.php不够,因为可能残留旧的注解扫描缓存 - CLI 环境陷阱:
php think route:cache在 Docker 构建阶段运行,但runtime/是挂载卷,构建时生成的文件上线即失效;应放在部署脚本中,在目标机器上执行 - 权限叠加问题:
php-fpm用户和deploy用户不同组,runtime/目录需设为g+s并统一属组,否则 Web 进程读不到 CLI 生成的缓存文件
最常被忽略的一点:路由缓存文件本身也是 PHP 脚本,它能否被 OPcache 加载,取决于 opcache.enable_cli=1 是否开启。没开这个,route.php 就只是个普通文件,每次 require 都重新编译——缓存白做。


















