急切负载有许多 &属于(循环引用/无限循环) [英] Eager load hasMany & belongsTo (circular reference/infinite loop)
问题描述
更新(解决方案)
- 如果您需要
$user->images
内的$image
之一的->user
关系,则$user
变量已经可用,因为您从中加载了->images
! - 不要使用
protected $with
Eloquent 属性.这是一种反模式. - 相反,在需要的地方/时间按需显式地按需加载关系(注意:它不应该阻止您保持干燥!)
- 如果您确实需要/想要,请参阅@nicksonyap 的答案.它确实有效(我相信 - 未经测试).
- If you need
->user
relationship from one of the$image
inside$user->images
, then$user
variable is already available cause you loaded the->images
from it! - Don't use
protected $with
Eloquent property. It's an anti-pattern. - Instead explicitly eager load relationships on-demand from where/when it's needed (Note: it should not prevent you to keep things DRY!)
- If you really need/want to, see @nicksonyap answer. It does the trick (I believe – not tested).
原创
我遇到了一个我认为很简单的问题:
I'm running into what I believe is a simple problem:
- 我有一个
User
对象,它有很多Image
s Image
属于User
...(逆关系)
- I have a
User
object that has manyImage
s Image
belongs toUser
... (inverse relation)
我的问题是我想同时加载 User
模型上的 images()
和 user()
代码>图像代码>模型.为此,我只需按照文档中的说明设置一个 $with
属性.
My problem is that I want to eager load both the images()
on the User
model and the user()
on the Image
model. To do so, I just setup a $with
property as explained in the docs.
我的用户
模型:
class User extends EloquentModel {
protected $with = ['images'];
public function images()
{
return $this->hasMany(Image::class);
}
}
我的图片
模型:
class Image extends EloquentModel {
protected $with = ['user'];
public function user()
{
return $this->belongsTo(User::class);
}
}
但是在表演时:
$user = User::find(203);
这会导致无限循环(php 分段错误).一定有某种我无法找到的循环引用:
This results in an infinite loop (php segmentation fault). There must be some kind of circular reference that I am not able to locate:
[1] 85728 segmentation fault
编辑 2016/02
这是我发现的最简单的解决方法":
This is the simplest "Workaround" I found:
// User.php
public function setRelation($relation, $value)
{
if ($relation === 'images') {
foreach ($value as $image) {
$image->setUser($this);
}
}
return parent::setRelation($relation, $value);
}
推荐答案
有一个 without()
方法:https://laravel.com/api/5.8/Illuminate/Database/Eloquent/Builder.html#method_without
将 without()
放在关系的双方都有效.
Placing without()
on both sides of a relationship worked.
class Property extends EloquentModel {
protected $with = ['images'];
public function images()
{
return $this->hasMany(Image::class)->without('property');
}
}
class Image extends EloquentModel {
protected $with = ['property'];
public function property()
{
return $this->belongsTo(Property::class)->without('images');
}
public function getAlt()
{
return $this->property->title;
}
}
更新:
尽管使用 without()
很容易避免无限循环问题,但通过多年使用 Laravel 的经验,我意识到在模型中设置 $with
是不好的做法它导致关系总是加载.因此导致循环引用/无限循环
Even though using without()
easily avoid the infinite loop issue, through years of experience with Laravel I realize it is bad practice to set $with
in the model as it causes relationships to always load. Hence leading to circular reference/infinite loop
相反,总是使用 with()
来明确指定 需要立即加载的必要关系,无论多么必要(关系的关系)
Rather, always use with()
to explicitly specify necessary relationships to be eager loaded, however deep necessary (relationship of relationship)
例如:
$user = User::with('images' => function ($query) {
$query->with('property' => function ($query) {
$query->with('deeperifneeded' => function ($query) {
//...
});
});
]);
注意:可能需要去掉without()
这篇关于急切负载有许多 &属于(循环引用/无限循环)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!