UPDATE (SOLUTION)
- 如果您需要
$user->images
内部$image
之一->user
关系,那么$user
变量已经可用,因为您从中加载了->images
! - 不要使用
protected $with
Eloquent 属性。这是一种反模式。 - 相反,明确地渴望从需要的地方/时间按需加载关系(注意:它不应该阻止你保持干燥!
- 如果您确实需要/想要,请参阅@nicksonyap答案。它确实可以解决问题(我相信 - 未经测试)。
源语言
我遇到了我认为是一个简单的问题:
- 我有一个
User
对象,它有很多Image
-
Image
属于User
...(反比关系)
我的问题是我想急切地加载User
模型上的images()
和Image
模型上的user()
。为此,我只需按照文档中的说明设置一个$with
属性。
我的User
模型:
class User extends EloquentModel {
protected $with = ['images'];
public function images()
{
return $this->hasMany(Image::class);
}
}
我的Image
模型:
class Image extends EloquentModel {
protected $with = ['user'];
public function user()
{
return $this->belongsTo(User::class);
}
}
但是在表演时:
$user = User::find(203);
这会导致无限循环(php 分段错误)。一定有某种我无法找到的循环引用:
[1] 85728 segmentation fault
编辑 2016/02
这是我发现的最简单的"解决方法":
// 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()
放在关系的双方是有效的。
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
是一种不好的做法,因为它会导致关系始终加载。因此导致循环引用/无限循环
相反,始终使用with()
来明确指定要急切加载的必要关系,无论需要多么深(关系关系)
例如:
$user = User::with('images' => function ($query) {
$query->with('property' => function ($query) {
$query->with('deeperifneeded' => function ($query) {
//...
});
});
]);
注意:可能需要删除without()
当您尝试查找属性时,该属性会预先加载它拥有的所有图像,并且每个图像都渴望加载它所属的属性,这是您尝试查找的属性,它将再次开始预先加载它拥有的所有图像。 等等...
我解决此问题的方法是不是在模型内部预先加载,而是在调用模型时通过预先加载。
因此,请使用以下内容:
$prop = Property::with('images')->find(203);
在属性模型中删除此行时:
protected $with = ['images'];
图像模型中的这一行:
protected $with = ['property'];
我希望这个解决方案对您有用。