不能直接用。thinkphp 8 的 responsecachemiddleware 默认仅缓存 text/html 响应,因内部通过 $response->ishtml() 判断,而 application/json 响应返回 false,直接跳过缓存逻辑;需改写中间件或改用 cache::remember() 手动缓存数据。

ThinkPHP 8 的 ResponseCacheMiddleware 能缓存 API 响应吗?
不能直接用。ThinkPHP 8 官方中间件 ResponseCacheMiddleware 默认只对 text/html 类型响应生效,API 接口返回的 application/json 不在缓存范围内——这是最常被忽略的前提。
原因很简单:该中间件内部通过 $response->isHtml() 判断是否启用缓存,而 JSON 响应的 isHtml() 返回 false,直接跳过后续逻辑。
- 如果你没改过源码,哪怕配置了
cache_control或设置了Cache-Control: public, max-age=3600,浏览器或 CDN 可能缓存,但 ThinkPHP 自身不会写入cache驱动(如 file、redis) - 真实场景中,你看到“缓存生效”,大概率是浏览器根据响应头自行缓存,不是框架层面的可编程缓存
- 想让 JSON 响应进 Redis/file 缓存,必须绕过
isHtml()检查或重写中间件逻辑
手动给 API 响应加缓存:用 Cache::remember() 包裹业务逻辑
这是最可控、兼容性最好、也最符合 ThinkPHP 设计习惯的方式。把缓存决策放在控制器/服务层,而非响应层,避免中间件的类型限制。
关键点在于:缓存的是「数据」,不是「响应对象」;响应只是把缓存取出来再包装成 JSON。
- 缓存键建议包含请求参数哈希,例如:
api_user_list_'.md5($request->get('page').$request->get('size')) - 避免用
$request->url()全路径作 key,URL 中可能含 token、timestamp 等动态参数,导致缓存失效或污染 - 设置合理过期时间,比如分页接口用
300(5 分钟),用户资料用3600(1 小时) - 注意缓存穿透:空结果也要缓存(如
null或空数组),并设较短过期(如 60 秒)
示例:
// 控制器方法内
$data = Cache::remember('api_orders_'.$user_id, 300, function () use ($user_id) {
return OrderModel::where('user_id', $user_id)->select()->toArray();
});
return json($data);
想复用 ResponseCacheMiddleware?得改它的 handle() 方法
如果你坚持走中间件路线(比如已有大量路由依赖统一缓存策略),就必须修改中间件源码或继承重写。官方版本不支持 JSON 响应缓存,没有开关可配。
核心改动只有两处:一是放宽响应类型判断,二是确保 Content-Type 是 application/json 时仍执行缓存写入。
- 不要直接修改 vendor 下的文件,应新建类继承
think\middleware\ResponseCache,重写handle() - 把原逻辑中的
if (!$response->isHtml()) { return $next($request); }改为允许application/json - 注意:缓存内容是完整响应体(含 JSON 字符串),不是解码后的数组,后续读取需原样输出,不能二次
json() - 如果用了 gzip 压缩,缓存前要先判断是否已压缩,否则可能缓存乱码
缓存失效和调试时最容易踩的三个坑
缓存看似简单,但在 API 场景下,失效逻辑比页面复杂得多,尤其涉及多端、登录态、参数敏感等场景。
-
Cache::remember()的闭包里调用$this->request或依赖容器实例时,闭包执行时机在缓存未命中时才触发,但若闭包里用了单例对象(如 Db),要注意连接状态是否还有效 - 用 redis 缓存 JSON 数据时,别直接存 PHP 数组,
Cache::remember()内部会自动序列化,但手动Cache::set()存数组可能导致反序列化失败,一律用json_encode()后存字符串更稳 - 本地开发开 debug 模式时,
AppDebug为 true 会强制关闭所有缓存(包括Cache::remember),切记上线前检查app_debug配置
缓存不是开关一开就完事,尤其是 API,每个接口的数据敏感度、更新频率、依赖关系都不同。硬套一个中间件或统一过期时间,反而容易出问题。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











