Laravel 5.8 Eloquent Observers测试及数据不更新问题求助
在Laravel 5.8中测试Eloquent Observers及问题排查思路
当然可以测试Eloquent Observers,Laravel自带的测试工具完全能覆盖这类场景的验证。针对你遇到的「Observer方法触发但数据库无变更」的问题,结合你贴的代码,我来拆解问题根源和通用排查思路:
你的代码问题根源
先看你的BookObserver@updated方法:
public function updated(Book $book) { $book->name = 'JAJCA'; }
这里你只是修改了内存中模型实例的属性,但没有调用save()或update()把变更同步到数据库!这就解释了为什么接口返回的模型是修改后的JAJCA(因为实例属性已经改变),但数据库里还是原来的值——内存中的变更没有被持久化。
修正Observer代码
你需要在Observer里明确执行持久化操作,但要注意避免死循环(因为update/save会再次触发updated事件):
public function updated(Book $book) { // 使用withoutEvents避免再次触发updated事件 $book->withoutEvents(function () use ($book) { $book->update(['name' => 'JAJCA']); }); }
测试相关的注意点
你用assertDatabaseHas()是正确的测试姿势,但要注意:
Laravel的HTTP测试(比如getJson)默认会开启数据库事务,测试结束后自动回滚所有操作。所以你在测试里直接用DB::table()->get()查询数据库是看不到变更的——因为事务还没提交。正确的做法是用框架提供的断言:
public function testBasicTest() { $user = factory(User::class)->create(); $book = Book::create([ 'user_id' => $user->id, 'name' => 'test' ]); $response = $this->getJson('/api/books-update?book_id=' . $book->id); $response->assertStatus(200); // 用框架断言验证数据库变更 $this->assertDatabaseHas('books', [ 'id' => $book->id, 'name' => 'JAJCA' ]); }
通用排查思路(针对Observer触发但数据库无变更)
- 检查Observer的持久化操作:确认是否在Observer里调用了
save()/update(),很多时候只是修改了模型实例属性却没同步到数据库 - 验证事务逻辑:检查业务代码或测试中是否有事务回滚的逻辑(比如Laravel测试默认的事务回滚),直接查询数据库可能看不到未提交的变更,要用框架断言
- 排查事件循环/拦截:是否有其他Observer、中间件或全局事件监听逻辑拦截了你的持久化操作
- 打印调试SQL:开启Laravel的SQL日志,查看是否有对应的更新语句执行,比如在测试中添加
DB::enableQueryLog(),然后dd(DB::getQueryLog()),确认更新语句是否正确发送到数据库
内容的提问来源于stack exchange,提问作者boka18
相关产品推荐
相关产品推荐

