根本原因是缓存清理路径与实际生效位置错位:删的是a目录,框架读的是b目录;清的是file驱动,业务用的是redis驱动;重启php-fpm但swoole进程仍持有旧缓存。

ThinkPHP线上环境执行清缓存命令后页面行为没变、新代码不生效、路由仍走旧逻辑,根本不是命令没敲对,而是缓存清理路径和实际生效缓存位置错位了——你删的是A目录,框架读的是B目录;你清的是file驱动,业务用的却是redis驱动;你重启了PHP-FPM,但Swoole进程还拿着旧缓存。
缓存路径被配置覆盖却没察觉
检查 config/cache.php 中 default 值是否为 'file',再打开 .env 文件,确认是否存在 CACHE_DRIVER=file 且未被其他变量(如 CACHE_PATH=/tmp/think_cache)覆盖;若 .env 里写了 CACHE_PATH,但 config/cache.php 中 stores['file']['path'] 没同步改,Cache::store('file')->clear() 就会去删默认的 runtime/cache/,而真实缓存文件其实在 /tmp/think_cache/ 里躺着。
这一步必须人工核对,不能只信 php think clear --all 的返回结果。
命令行清缓存 ≠ 运行时清缓存
方法一:用 CLI 执行 php think clear --all —— 它只清 runtime/cache/、runtime/log/、runtime/temp/,但不会碰 runtime/view/(模板缓存)、runtime/schema/(字段缓存)、runtime/route.php(路由缓存),更不会连 Redis 里的数据一起清。
方法二:在控制器里写 Cache::clear() —— 这个调用依赖容器自动初始化,而 CLI 环境下部分自定义驱动可能根本没注册,导致它悄悄 fallback 到 Null 驱动,返回 true 却什么都没删。
【务必显式指定驱动名】:改成 Cache::store('redis')->clear() 或 Cache::store('file')->clear(),避免因驱动未加载导致静默失败。
多缓存类型必须分头清理
第一步:清模板缓存 → 删除整个 runtime/view/ 目录(别只删 *.php,哈希子目录里的文件通配符匹配不到)
第二步:清路由缓存 → 执行 php think clear:route,不是 php think clear
第三步:清字段缓存 → 运行 \think\facade\Db::clearCache() 或手动删 runtime/schema/ 下对应表的 PHP 文件
第四步:清注解路由 → 先 php think clear:route,再确保 APP_DEBUG=false 且 runtime/ 可写,最后执行 php think route:cache --annotation
Swoole/RoadRunner 进程锁住缓存文件
如果项目用了 Swoole 或 RoadRunner,runtime/temp/ 和 runtime/cache/ 下的部分 PHP 编译文件可能被常驻进程锁定,直接 rm -rf runtime/cache 会失败或删不干净。
必须先 reload 服务:php think swoole restart 或 kill -USR2 $(cat swoole.pid),等进程释放文件句柄后再清理。
否则你看到的“已删除”只是 Linux 的 unlink 行为,文件实体仍在磁盘上,直到进程退出才真正释放。
Redis 缓存清理漏掉标签索引
执行 Cache::tag('user')->clear() 没反应?先确认驱动是否支持标签:只有 file、redis、memcached 实现了完整标签清理,apc 和 wincache 调了也白调。
再检查 config/cache.php 中 redis store 的 tag_prefix 是否设为 'tp_tag:' —— 如果没设,索引 key(如 tp_tag:user)和真实数据 key(如 think_user_123)对不上,clear() 就找不到要删的东西。
手动兜底方案:用 Redis CLI 执行 scan 0 match tp_tag:user:* count 1000 查出所有索引项,对每个结果运行 smembers {key} 获取真实 key 列表,再逐个 del {real_key},最后 del {index_key}。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











