急切负载有许多 &属于(循环引用/无限循环) [英] Eager load hasMany & belongsTo (circular reference/infinite loop)

查看:12
本文介绍了急切负载有许多 &属于(循环引用/无限循环)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新(解决方案)

  • 如果您需要 $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 对象,它有很多 Images
  • Image 属于 User...(逆关系)
  • I have a User object that has many Images
  • Image belongs to User... (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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆