【问题标题】:Eager load only if relationship exists仅当存在关系时才加载
【发布时间】:2017-10-19 10:44:43
【问题描述】:

我有一个变形关系,主题可能有多个关系。它们的存在取决于变形模型。我需要检索所有相关模型(whereHas() 不能解决问题),如果它们存在于特定模型上,我希望加载它们的关系(with() 不起作用,因为关系并不总是存在) .

我可以使用其他任何东西(内置)来流畅地解决这种情况,或者黑客是解决它的唯一方法吗?

<?php

...

class Post extends Model
{
    /**
     * Get all of the post's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }

    /**
     * This relationship is available for Post model only
     */
    public function relationA()
    {
        // return $this->hasMany(...);
    }
}

class Video extends Model
{
    /**
     * Get all of the video's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }

    /**
     * This relationship is available for Video model only
     */
    public function relationB()
    {
        // return $this->hasMany(...);
    }
}

class Comment extends Model
{
    /**
     * Get all of the owning commentable models.
     */
    public function commentable()
    {
        return $this->morphTo();
    }

    public static function feed()
    {
        self::with('commentable')
            ->withIfExists(['commentable.relationA', 'commentable.relationB'])
            // ...
            ->get();
    }

    public function scopeWithIfExists($query, $relation)
    {
        // There is no way to implement such a scope
        // in order to reduce umber of queries by eager loading relations
        // as we don't know of what type the subject is
        // without looking it up in database
    }
}

【问题讨论】:

    标签: laravel laravel-5 eager-loading


    【解决方案1】:

    查看Query Scopes

    有了它,您可以创建一个范围来加载关系(如果存在),例如:

    User::withRelationIfExists('cars')->where(...)
    

    例如:(代码未测试)

    public function scopeWithRelationIfExists($query, $relation)
    {
        if (! method_exists(get_class(), $relation)) {
            return;
        }
    
        return $query->with($relation);
    }
    

    【讨论】:

    • 我认为这种方法并不能解决问题。它要么加载它,要么不加载它,但对于所有人。所以你要么在当前模型上定义了关系,laravel 会急切地加载它,也不会加载它。还是我错过了什么?
    • 此方法是一个自定义帮助器,可以轻松加载关系而无需一直检查它。如果你想使用它,你需要在 Model 中声明该方法,或者创建一个 Parent 模型来继承,或者将它添加到一个 Trait 并在你想要这个自定义范围的模型中使用它。如果您不知道关系的名称,则无法告诉 Laravel 自动加载关系。
    • 我了解作用域,我开始按照你建议的方式实现它,但有一点我意识到它没有意义,因为如果你有 morphMany 关系,则对象的类将被存储在数据库中(因为可能有各种类型,对吧),所以你不能在查询db之前检查是否存在这样的关系,这就是它全部中断的地方。
    • 我添加了一些代码,以便您更好地理解我在说什么
    • 在我看来,多态关系使您能够从数据库字段 commentable_typecommentable_id 加载模型或其他模型。但是您仍然需要声明 public function commentable() 关系。
    猜你喜欢
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2014-03-11
    相关资源
    最近更新 更多