测试oneToMany关系Laravel,Eloquent不起作用

时间:2016-04-03 16:55:01

标签: laravel eloquent relationship

我无法理解这一点:

$fragment = factory(Fragment::class)->create();

$this->assertCount(0, $fragment->values);

fragment->fetch(); // updates the 'values' by adding one Value object.

var_dump($fragment->id); // i.e. 6
var_dump(Fragment::first()->id); // 6 

var_dump($fragment->values->count());  // 0
var_dump(Fragment::first()->values->count()); // 1

$this->assertCount(1, $fragment->values);

我使用DatabaseTranscations,因此在创建片段后,总会有一个且只有一个片段。因此,$ fragment和Fragment :: first()是完全相同的实例。然而......价值观关系是不同的。情况怎么样?

请注意,这只发生在测试期间,当我通过我的控制器手动测试它(并且值传递到刀片模板页面)时它才能正常工作。我很困惑:S。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

关系属性($fragment->values)仅加载一次。当您添加或删除关系中的项目时,它们不会保持最新。他们每次都不会访问数据库以检查更改。

你的第二行是$this->assertCount(0, $fragment->values);。在这里访问$fragment->values延迟加载关系,并且正如你的断言所证明的那样,它是空的。

然后,您调用$fragment->fetch(),其中您的评论说它会在片段中添加Value个对象。但是,您的关系属性($fragment->values)已经从前一个语句加载,因此它不会反映您添加到关系中的其他Value对象。

因此,即使在调用fetch()之后,$fragment->values仍然是一个空集合。 Fragment::first()->values会包含新关联的Value,因为它正在获取Fragment的新实例,并且当它第一次加载values时,它会选择相关的Value

当您需要重新加载关系时,可以使用load()方法。如果您在致电fetch()之后添加此内容(或将其放入fetch()方法中,以适用者为准),您的测试将正常运行。

$fragment = factory(Fragment::class)->create();

$this->assertCount(0, $fragment->values);

$fragment->fetch(); // updates the 'values' by adding one Value object.

var_dump($fragment->id); // i.e. 6
var_dump(Fragment::first()->id); // 6 

var_dump($fragment->values->count());  // 0

// reload the values relationship
$fragment->load('values');

var_dump($fragment->values->count());  // 1
var_dump(Fragment::first()->values->count()); // 1

$this->assertCount(1, $fragment->values);

您拥有的另一个选项是通过访问关系方法而不是关系属性来使用关系查询。如果您执行$fragment->values()->count()(注意:values(),而不是values),那么每次都会访问数据库并始终返回当前计数。