Laravel Eloquent updating observer中getRawOriginal返回新值及事务兼容方案问询
问题根因说明
Laravel 框架默认的updating事件确实会在SQL写入数据库前触发,你遇到的原始值获取失效、事件看似延迟触发的问题,核心原因是事件/观察者的$afterCommit配置开启:
当观察者类中声明了public $afterCommit = true,或者对应事件的监听器配置了事务后执行,事件会推迟到整个事务提交完成后再派发,此时模型的原始值已经被新值覆盖,自然无法通过getRawOriginal拿到更新前的内容。你移除事务后逻辑恢复正常,完全符合该配置的生效逻辑。
无需移除事务的解决方案
方案1:关闭对应观察者的afterCommit配置(最优解)
直接在User观察者类中关闭事务后执行的配置,强制updating事件按默认时机触发:
class UserObserver { // 新增以下配置即可 public $afterCommit = false; public function updating(User $user) { Log::info('Original user', ['original' => $user->getRawOriginal('status')]); // 原有对比逻辑直接在这里正常执行即可 } }
该方案改动最小,不影响事务的其他逻辑。
方案2:更新前手动保存原始值
如果因其他业务要求必须保留$afterCommit配置,可以在调用更新方法前先查询并存储需要对比的原始值:
public function update(array $user, int $userId): ?bool { $userModel = User::find($userId); // 提前保存需要对比的字段原始值 $originalStatus = $userModel->getRawOriginal('status'); $updateResult = $userModel->update($user); // 直接在当前位置执行值对比逻辑 Log::info('值对比结果', [ 'original_status' => $originalStatus, 'new_status' => $user['status'] ?? $originalStatus ]); return $updateResult; }
方案3:使用模型saving事件替代
如果观察者的updating事件被全局配置强制要求延迟执行,可以改用更早期的saving事件监听,该事件触发时机更早,不受afterCommit配置的影响,在事务场景下也能正常拿到原始值。
内容的提问来源于stack exchange,提问作者R. Vait
相关产品推荐
相关产品推荐

