【问题标题】:How to add where condition to eloquent model on relation?如何在关系模型中添加 where 条件?
【发布时间】:2016-10-29 11:02:31
【问题描述】:

我想在调用 with('category') 时向我的模型添加 where 条件。我的关系是这样的:

class Post extends Model
{
    public function category()
    {
        return $this->belongsTo(Category::class);
    }
}

现在我使用此代码显示帖子类别:

Post::where('slug', $slug)->with('category')->get();

我想在调用 with('category') 时将 where 条件添加到 Post Model。如果调用了with('category'),我应该只显示posts.status== published

我认为return $this->belongsTo(Category::class); 是我应该添加我的 where 条件的地方,但这不起作用:

return $this->query()->where('posts.status', 'published')->getModel()->belongsTo(User::class)

如果调用 with('category'),我如何向所有帖子查询添加 where 条件? 我知道 Laravel 查询范围,但我认为我们可以使用一种更简单的方法。 (也许在$this->belongsTo(Category::class)

【问题讨论】:

    标签: php mysql laravel laravel-5 eloquent


    【解决方案1】:

    关系是使用附加查询来实现的。它们不是基本查询的一部分,也无权修改基本查询,因此您不能在关系方法中执行此操作。

    最好的方法是使用查询范围:

    类:

    class Post extends Model
    {
        public function scopeWithCategory($query)
        {
            return $query->with('category')->where('status', 'published');
        }
    }
    

    查询:

    $posts = Post::where('slug', $slug)->withCategory()->get();
    

    编辑

    根据您的评论,我认为您可能问错了问题。您可能想发布另一个问题,解释您的设置以及您需要做什么,看看是否有人有任何建议。

    但是,要回答这个特定问题,我相信您应该能够使用global query scope 来完成此操作。这与我上面原始答案中描述的本地范围不同。

    在 Eloquent 查询构建器上调用 get() 时应用全局查询范围。他们可以访问查询构建器对象,并且可以查看已请求急切加载的项目。因此,您应该能够创建一个全局查询范围来检查是否要预先加载 category,如果是,请添加 status 约束。

    class Post extends Model
    {
    
        /**
         * The "booting" method of the model.
         *
         * @return void
         */
        protected static function boot()
        {
            // make sure to call the parent method
            parent::boot();
    
            static::addGlobalScope('checkCategory', function(\Illuminate\Database\Eloquent\Builder $builder) {
                // get the relationships that are to be eager loaded
                $eagers = $builder->getEagerLoads();
    
                // check if the "category" relationship is to be eager loaded.
                // if so, add in the "status" constraint.
                if (array_key_exists('category', $eagers)) {
                    $builder->where('status', 'published');
                }
            });
        }
    }
    

    上面的代码显示了使用匿名函数在全局范围内添加。这样做是为了方便和清晰。我建议创建实际的范围类,如上面链接的文档中所述。

    【讨论】:

    • 就我而言,很难使用范围,因为我实现了存储库模式并且查询在 REST API 上运行。我将查询字符串过滤器发送到哪里。除了关系方法还有更简单的方法吗?
    【解决方案2】:

    这应该可行:

    Post::where(['slug' => $slug, 'status' => 'published'])->with('category')->get();
    

    【讨论】:

    • 是的,这可行,但我想以更简单的方式将其添加到所有查询中。谢谢。
    【解决方案3】:

    你必须使用 withPivot() 方法。

        class Post extends Model
    {
        public function category()
        {
            return $this->belongsTo(Category::class)->withPivot('status');
        }
    }
    

    请参考我的问题here

    【讨论】:

    • 我不是-1,但这是一个无关紧要的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 2020-01-01
    相关资源
    最近更新 更多