用 refresh() 方法可轻量同步模型实例字段值,但不触发事件、不校验、不走访问器、不更新关联;适用于订单轮询等需避免重建实例的场景,失败主因是主键为空或记录不存在。

直接说结论:用 refresh() 方法,但必须注意它只刷新当前模型实例的属性,不触发事件、不校验、不走访问器,且对关联关系无效。
什么时候该用 refresh() 而不是重新查库?
当你已有一个 Eloquent 模型实例(比如从缓存或上一步操作拿到),但数据库里对应记录可能被其他请求改过,需要同步最新字段值——这时比 Model::find($id) 更轻量,避免重复查询主键和重建实例。
- 适用场景:订单状态轮询、后台管理页“强制刷新”按钮、并发写入后校验最终值
- 不适用场景:需要触发
retrieved事件、依赖get*访问器逻辑、要同步belongsTo关联数据 - 注意:
refresh()会重置$model->wasChanged()和脏数据标记,后续调用isDirty()全为false
refresh() 刷新失败的常见原因
最典型的是模型实例处于“不可刷新”状态:主键为空、主键值在数据库中已不存在、或表里没有对应记录。
- 错误现象:
Illuminate\Database\Eloquent\ModelNotFoundException或返回null(取决于是否开启异常抛出) - 检查点:
$model->exists必须为true,且$model->getKey()有值(如123) - 陷阱:软删除模型若已被删除,
refresh()不会自动跳过,需提前判断$model->trashed() - 调试建议:执行前加
dd($model->toArray(), $model->getKey());确认主键和当前状态
关联数据不会跟着 refresh() 更新
refresh() 只作用于当前模型的原始属性(即 $model->attributes),所有 with() 预加载或懒加载的关联($model->user、$model->posts)保持原样,仍是旧引用。
- 如果需要更新关联,得手动再调用:
$model->load('user', 'posts') - 想一次性刷新主模型 + 所有关联?没有内置方法,得组合:
$model->refresh()->load('user', 'posts') - 性能提醒:多次
load()会产生额外 SQL,高并发下慎用;不如直接Model::with('user', 'posts')->find($id)
真正容易被忽略的点是:刷新后的模型仍保留原始的 $casts 和 $dates 处理逻辑,但不会重新运行 get* 访问器——比如你定义了 getFullNameAttribute(),refresh() 后 $model->full_name 还是旧值,除非你显式访问它触发访问器。这种“半刷新”状态,恰恰是线上排查数据不一致时最隐蔽的坑。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











