首页 文章

关系的雄辩查询范围

提问于
浏览
4

我有两个型号,App \ Song(belongsTo App \ Host)和App \ Host(hasMany App \ Song) .

我的控制器中有以下查询:

$songs = Song::whereHas('host', function($query) {
                $query->where('skip_threshold', '>', \DB::raw('songs.attempts'))
                      ->where('active', 1);
            })
->whereNull('downloaded')
->get();

为了可重用性,我想变成一个查询范围 .

我对Eloquent很陌生,所以我不确定这是不是正确的方法,因为它的两个模型没有返回任何结果(应该在哪里) .

Song.php

public function scopeEligable($query)
{
    $query->where('skip_threshold', '>', \DB::raw('songs.attempts'));
}

public function scopeActiveHost($query)
{
    $query->where('active', 1);
}

public function scopeInDownloadQueue($query)
{
    $query->whereNull('downloaded');
}

2 回答

  • 0

    您应该将范围放入它们所属的模型中 . 查看您的初始查询范围 scopeEligablescopeActiveHost 属于 Host 模型,因此您应该将它们移动到 Host 模型中,然后您将能够使用这样的范围来使用您的查询:

    $songs = Song::whereHas('host', function($query) {
       $query->eligable()->activeHost();
    })->inDownloadedQueue()->get();
    

    正如已在评论中指出的那样,您应该将 return 添加到每个范围,以便它们可以按预期使用 .

    EDIT

    如果您想缩短使用它,可以在 Song 模型中创建新关系:

    public function activeHost() 
    {
        return $this->belongsTo(Host:class)->eligable()->activeHost();
    }
    

    所以现在,你可以写:

    $songs = Song::whereHas('activeHost')->inDownloadedQueue()->get();
    
  • 4

    我觉得你错了两个模特 . 我认为这应该有效

    Song.php

    public function scopeEligable($query, $active) {
       return $query->whereHas('host', function($q) {
           $q->where('skip_threshold', '>', \DB::raw('songs.attempts'))->where('active', $active);
       })
    }
    
    public function scopeInDownloadQueue($query)
    {
       $query->whereNull('downloaded');
    }
    

    Usage

    $songs = Song::eligable(true)->inDownloadQueue()->get();
    

相关问题