
Laravel 中使用 Redis 缓存时,若控制器方法参数启用了隐式路由模型绑定(如 show(Application $application)),模型会在缓存逻辑执行前被自动查询并实例化,导致 Cache::remember() 实际缓存的是已加载的模型对象而非数据库查询结果,从而完全绕过缓存机制。
laravel 中使用 redis 缓存时,若控制器方法参数启用了隐式路由模型绑定(如 `show(application $application)`),模型会在缓存逻辑执行前被自动查询并实例化,导致 `cache::remember()` 实际缓存的是已加载的模型对象而非数据库查询结果,从而完全绕过缓存机制。
在 Laravel 8(及更高版本)中,当您定义控制器方法形参为具体模型类型(如 Application $application)时,Laravel 会自动触发隐式路由模型绑定:框架在进入方法体之前,就已通过路由参数(如 /applications/123)执行 Application::find(123) 并注入实例。这意味着——即使您后续在 Cache::remember() 的闭包中再次调用 Application::find($application),此时 $application 已是一个已加载的 Eloquent 模型对象,而非原始 ID;而 find() 方法接收模型实例时将直接返回该实例,根本不会发起数据库查询,更不会触发缓存写入。
因此,您观察到的现象——“浏览器请求始终慢、Tinker 中手动执行却能缓存”——本质是:
✅ Tinker 中调用 Application::with(...)->find($id) 时传入的是整数 ID,真正执行了查询并被缓存;
❌ 浏览器请求中,$application 是已实例化的模型,find($application) 返回原对象,闭包未执行实际查询,remember() 因未执行闭包而不写入缓存,后续请求重复触发完整查询,导致 8 秒延迟。
✅ 正确做法:禁用隐式绑定,显式传入 ID
修改控制器方法签名,移除模型类型提示,仅接收原始 ID 参数:
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function show($id)
{
$application = Cache::store('redis')->remember(
"application:{$id}",
now()->addMinutes(30),
function () use ($id) {
return Application::with([
'payday', 'response', 'apiLinks'
])->find($id); // 注意:find($id) 已返回模型,无需再链式调用 ->first()
}
);
return response()->json(['application' => $application], 200);
}⚠️ 注意事项:
- Application::find($id) 本身即返回单个模型或 null,->first() 在此冗余且可能引发错误(Call to a member function first() on null),应删除;
- 缓存键建议统一格式,如 "application:{$id}",避免因对象 toString 行为(如 "$application" 可能输出类名+哈希)导致键不稳定;
- 若仍需保留模型绑定语义,可改用显式绑定并在路由服务提供者中自定义解析逻辑,但通常直接传递 ID 更清晰、更可控;
- 验证 Redis 连接与缓存驱动配置(CACHE_DRIVER=redis,REDIS_CLIENT=predis)无误,可通过 php artisan tinker 执行 Cache::store('redis')->put('test', 'ok', 60) 快速验证。
通过剥离模型绑定与缓存逻辑的耦合,确保 Cache::remember() 的闭包始终承载真实的数据获取行为,才能让 Redis 缓存真正生效,将 8 秒响应降至毫秒级。



















