急切加载对 Laravel 中的模型事件/启动有一些意想不到的副作用
Posted
技术标签:
【中文标题】急切加载对 Laravel 中的模型事件/启动有一些意想不到的副作用【英文标题】:Eager loading has some unexpected side effects on Model events/ booting in Laravel 【发布时间】:2013-12-07 15:53:51 【问题描述】:我正在尝试创建一些测试。
这是我的测试类:
class ExampleTest extends TestCase
public function setUp()
parent::setUp();
Artisan::call('migrate');
$this->seed();
Auth::loginUsingId(1);
public function testActionUpdateNew()
$action = new Action(Array());
$action->save();
var_dump($action->id);
Action::with('reponses','contact','user','etudiant','entreprise','etude')->findOrFail($action->id);
public function testEtudes()
$etudes=Etude::all()->toArray();
$this->assertCount(10, $etudes, "Nombre d'études incorrectes");
$numEtudes=count($etudes);
//Buggy part
$etude= Etude::create(Array());
var_dump($etude->id);
$etudes=Etude::all()->toArray();
$this->assertCount(11, $etudes, "Nombre d'études incorrectes");
//10+1 should equal to 11 but it hasnt updated
没有通过的测试是第二个:我数了数eloquent Objects Etudes的数量,一开始是10个,然后我在数据库中添加一个etude(使用Etude::create()),对象被创建,因为 $etude->id 给出了一个实数。但是,练习曲的数量没有更新。
当我从 Action::with('reponses',...) 中的急切加载中删除“练习曲”时,问题确实消失了
这是Action类中的练习曲关系:
public function etude()
return $this->belongsTo('Etude');
你们知道在 laravel 中预加载是否会出现这种奇怪的行为以及如何解决这个问题吗?
编辑
我发现 with('etude') 调用具有删除注册到 Eloquent 模型的事件的操作:
练习曲的引导方法:
public static function boot()
parent::boot();
static::creating(function($etude)
var_dump("creating etude"); //This doesn't get executed even when I run Etude::create(Array());
);
所以如果我在 testEtudes 的开头添加 Etude::boot(),它会再次起作用。这还是很奇怪。
急切加载对事件或启动方法有任何影响吗?还是每次测试后都不会自动调用boot方法?
【问题讨论】:
您确定它已保存/$action->id 是有效值吗?异常消息是什么? 嗨,当我添加 var_dump($action->id); 时,我得到 2836(一个真实值),异常消息是一个空字符串:“”(这是正常的,因为它是扔在这里:laravel.com/api/…) 你确定它完全抛出异常吗?我希望看到堆栈跟踪。我在 Laravel 中的单元测试方面做得不多,但也许它只是没有打印任何东西。尝试用 echo 交换 return。 返回 echo 并不能解决问题。堆栈跟踪可以在这里找到:pastebin.com/QDNcBGhy 这真的很奇怪,因为当我将该代码放在 ExampleTest 类的顶部时,它通过了。 【参考方案1】:在 Laravel 测试中,事件调度器在每次测试之间都会重置,但模型仍然只启动一次,因为它们过着非常独立的生活。这意味着在每次测试之间,模型侦听器都会被删除,但不会重新注册。解决方案是不使用boot()
来注册模型事件,而是将它们放在一个单独的文件中 - 服务提供者或 app/start/global.php 中包含的文件(app/events.php 是一个常见的文件) .
【讨论】:
以上是关于急切加载对 Laravel 中的模型事件/启动有一些意想不到的副作用的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 混合获取 Eloquent 急切加载嵌套多个模型