渴望加载hasMany& belongsTo(循环引用/无限循环)

时间:2016-01-25 14:38:39

标签: laravel-5 eloquent eager-loading

更新(解决方案)

  • 请勿使用protected $with Eloquent属性。这是一种反模式。
  • 而是明确地根据需要从何处/何时开始按需加载关系(注意:它不应该阻止您保持干燥!)
  • 如果您需要->property $image内部$property->images父关系之一的$property关系,那么(父)->images变量已经可用,因为您加载了{{1}来自它!
  • 如果你真的需要/想要,请参阅@nicksonyap回答。这样做(我相信 - 没有经过测试)。

ORIGINAL

我遇到了我认为是一个简单的问题:

  • 我有一个Property对象有很多 Image s
  • Image 属于 Property ...(反向关系)

我的问题是,我希望加载images()模型上的Propertyproperty()模型上的Image。为此,我只需按照文档中的说明设置$with属性。

我的Property型号:

class Property extends EloquentModel {
    protected $with = ['images'];

    public function images()
    {
        return $this->hasMany(Image::class);
    }
}

我的Image型号:

class Image extends EloquentModel {
    protected $with = ['property'];

    public function property()
    {
        return $this->belongsTo(Property::class);
    }
}

但表演时:

$prop = Property::find(203);

这导致无限循环(php分段错误)。必须有某种我无法找到的循环引用:

[1]    85728 segmentation fault

EDIT 2016/02

这是我发现的最简单的“解决方法”:

// Property.php
public function setRelation($relation, $value)
{
    if ($relation === 'images') {
        foreach ($value as $image) {
            $image->setProperty($this);
        }
    }
    return parent::setRelation($relation, $value);
}

2 个答案:

答案 0 :(得分:2)

有一个without()方法(在Laravel 5.4上测试) https://laravel.com/api/5.4/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;
    }
}

答案 1 :(得分:0)

当你试图找到一个Property时,该属性渴望加载它拥有的所有图像,每个Image eager加载它所属的属性,这是你试图找到的属性,这将再次开始急切加载所有图像它有。等...

我解决这个问题的方法是不急于在模型中加载,而是在调用模型时急切加载。

所以使用以下内容:

$prop = Property::with('images')->find(203);

在Property模型中删除此行时:

protected $with = ['images'];

图像模型中的这一行:

protected $with = ['property'];

我希望这个解决方案适合你。