ThinkPHP 8.0 数据缓存需显式调用 Cache::set() 并确保 Redis 驱动真实连通,配置须在 config/cache.php 中明确设置 redis 为 default,逐项核对 host、port、database 等参数,通过 ping 验证连接,使用带标签或业务参数的缓存键,并通过响应时间、日志标记和 model_cache.php 文件确认缓存生效。

ThinkPHP 8.0 实现数据缓存不是改个配置就能生效的事,必须显式调用 Cache::set() 并确保底层驱动真实连接 Redis 或其他高速存储,否则即使代码写了缓存逻辑,也会静默降级为 file 驱动——你看到 Cache::set() 返回 true,但 Cache::get() 拿不到值,就是最典型的失效信号。
确认缓存驱动已真正启用
打开 config/cache.php,检查 'default' 键是否明确设为 'redis':【不能只靠 .env 中 CACHE_STORE=redis 开关,TP8 完全不读取 REDIS_HOST 等环境变量】。
在 stores['redis'] 数组中逐项核对:host 必须是字符串(如 '127.0.0.1'),port 必须是整型(6379),database 必须指定(如 0),timeout 建议 float 类型(3.0),persistent 强烈建议设为 true。
运行 php think tinker → 执行 (new \think\cache\driver\Redis(config('cache.stores.redis')))->handler()->ping();返回 +PONG 才算连通,返回 false 或异常说明配置有误或网络不通。
立即学习“PHP免费学习笔记(深入)”;
基础数据缓存写法(直接存取)
方法一:单键存取
Cache::set('user_1001', ['name' => '张三', 'age' => 28], 3600);这一步操作起来很简单,直接传入键、值、秒数即可。
Cache::get('user_1001') 即可取回数据;若返回 null,先别怀疑代码,回头验证上一步的 ping 是否成功。
方法二:带标签的批量管理
Cache::tag('user')->set('profile_1001', $data, 3600);Cache::tag('user')->set('setting_1001', $conf, 7200);
后续可用 Cache::clear('user') 一次性清空所有打上 user 标签的缓存项,比逐个 del 更安全可控。
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
模型查询结果缓存(精准命中关键)
第一步:禁用 cache(true)
全局搜索项目中所有 cache(true),全部替换为显式键名形式;【cache(true) 只对 find(1) 这类无参静态查询安全,其余场景极易因 SQL 差异导致缓存键冲突或完全不生效】。
第二步:构造含业务参数的缓存键
使用数组而非字符串拼接:UserModel::where('status', $status)->cache(['user_list', $status, $type, $page], 600)->select();TP 会自动 serialize + md5,避免 $status=1 和 $status='1' 被识别为不同键。
第三步:关联查询单独加 cache()
在模型的关联方法里写:return $this->hasOne(Profile::class)->cache(['profile', $this->id, $this->delete_time], 3600);【软删除场景下,delete_time 必须纳入缓存键,否则逻辑删除后仍返回旧数据】。
验证缓存是否真在工作
① 清空当前缓存:php think cache:clear --tag=user
② 刷新接口,观察响应头 X-Response-Time 数值;再刷一次,若下降超过 150ms,说明缓存已介入。
③ 在控制器中插入 dump(Db::getLastSql());紧接着执行 select();日志里出现 “[CACHE HIT]” 才代表命中,没有就说明没走缓存路径。
④ 检查 runtime/cache/ 目录下是否存在 model_cache.php 文件;【没有该文件说明模型缓存根本未启动】。


















