雄辩的关系查询范围

Inv*_*tax 6 php laravel eloquent

我有两个模型,App \ Song(属于App \ Host)和App \ Host(有很多App \ Song)。

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

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

为了可重用性,我想转到一个查询范围。

我对Eloquent还是很陌生,所以我不确定这是否是正确的方法,因为它的两个Model不会返回任何结果(应该存在)。

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');
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*łek 7

您应该将范围放入它们所属的模型中。查看您的初始查询范围scopeEligablescopeActiveHost属于Host模型,因此您应将它们移入Host模型,然后可以使用如下范围使用查询:

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

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

编辑

如果要缩短使用时间,可以在Song模型中创建新的关系:

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

所以现在,您可以这样写:

$songs = Song::whereHas('activeHost')->inDownloadedQueue()->get();
Run Code Online (Sandbox Code Playgroud)