lundi 25 janvier 2016

Eager load hasMany & belongsTo (circular reference/infinite loop)

I'm running into what I believe is a simple problem:

  • I have a Property object that has many Images
  • Image belongs to Property... (inverse relation)

My problem is that I want to eager load both the images() on the Property model and the property() on the Image model. To do so, I just setup a $with property as explained in the docs.

My Property model:

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

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

My Image model:

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

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

    public function getAlt()
    {
        return $this->property->title;
    }
}

But when performing:

$prop = Property::find(203);
foreach ($prop->images as $img) {
    var_dump($img->getAlt());
}

This results in an infinite loop (php hanging). There must be some kind of circular reference that I am not able to locate.

I also tried to eager load only the Property::images() because I would expect that the belongsTo side of the relationship is easy to set (see my workaround after).

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

But no, the Image::property() relation is not set when Property receives all the eager loaded images.

Workaround

As a workaround I was able to accomplish what I want, like so:

class Property extends EloquentModel {
    ...

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

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

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

    protected $property;

    public function setProperty($property)
    {
        $this->property = $property;
    }

But how to achieve that in a more Eloquent way?



from Newest questions tagged laravel-5 - Stack Overflow http://ift.tt/1Nv4MdW
via IFTTT

Aucun commentaire:

Enregistrer un commentaire