急切加载 hasMany & BeingsTo(循环引用/无限循环)

eig*_*ive 6 eager-loading eloquent laravel-5

更新(解决方案)

  • 如果您需要内部的->user关系,那么变量已经可用,因为您从中加载了!$image$user->images$user->images
  • 不要使用protected $withEloquent 属性。这是一种反模式。
  • 而是明确地从需要的地方/时间按需加载关系(注意:它不应该阻止您保持干燥!)
  • 如果您真的需要/想要,请参阅@nicksonyap 答案。它可以解决问题(我相信 - 未经测试)。

原来的

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

  • 我有一个有很多s的User对象 Image
  • Image 属于 User...(逆关系)

我的问题是,我想急于负荷均images()User模型和user()Image模式。为此,我只是$with按照文档中的说明设置了一个属性。

我的User型号:

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

    public function images()
    {
        return $this->hasMany(Image::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的Image型号:

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

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是在表演的时候:

$user = User::find(203);
Run Code Online (Sandbox Code Playgroud)

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

[1]    85728 segmentation fault
Run Code Online (Sandbox Code Playgroud)

编辑 2016/02

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

[1]    85728 segmentation fault
Run Code Online (Sandbox Code Playgroud)

Nic*_*Yap 11

有一个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');
    }
}
Run Code Online (Sandbox Code Playgroud)
class Image extends EloquentModel {
    protected $with = ['property'];

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

    public function getAlt()
    {
        return $this->property->title;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

尽管使用without()轻松避免了无限循环问题,但通过多年的 Laravel 经验,我意识到$with在模型中进行设置是不好的做法,因为它会导致总是加载关系。因此导致循环引用/无限循环

相反,总是使用with()明确指定要急切加载的必要关系,无论多么必要(关系的关系)

例如:

$user = User::with('images' => function ($query) {
            $query->with('property' => function ($query) {
                $query->with('deeperifneeded' => function ($query) {
                    //...
                });
            });
        ]);
Run Code Online (Sandbox Code Playgroud)

注意:可能需要删除 without()

  • 那可行。我接受了你的答案(大约三年后......),尽管我建议反对它并支持明确性(请参阅我的更新)。 (2认同)