Php 关于关系的雄辩的查询范围

Php 关于关系的雄辩的查询范围,php,laravel,eloquent,Php,Laravel,Eloquent,我有两种型号,App\Song(belongsTo App\Host)和App\Host(有许多App\Song) 我的控制器中有以下查询: $songs = Song::whereHas('host', function($query) { $query->where('skip_threshold', '>', \DB::raw('songs.attempts')) ->where('active'

我有两种型号,App\Song(belongsTo 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();
为了可重用性,我想将其转换为一个查询范围

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

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');
}
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');
}

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

$songs = Song::whereHas('host', function($query) {
   $query->eligable()->activeHost();
})->inDownloadedQueue()->get();
正如注释中已经指出的,您应该将
return
添加到每个范围中,以便它们可以按预期使用

编辑

如果您想缩短使用时间,可以在
Song
model中创建新关系:

public function activeHost() 
{
    return $this->belongsTo(Host:class)->eligable()->activeHost();
}
现在,你可以写:

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

我认为你对两种型号的看法是错误的。我认为这应该行得通

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');
}
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');
}
用法

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

控制器中用于调用这些查询范围的代码是什么?(没有返回结果?
Song::eligable()->activehost()->indownloadqueue()->get()
在所有作用域中都应该有
return
<代码>返回$query->whereNull('下载')。作用域应始终返回查询生成器实例。我已经更新了返回查询的作用域,但是仍然没有返回任何数据。您可能需要直接查看sql。您是否安装了DebugBar?如果没有,请在查询调用之前尝试此操作\事件::侦听('light.query',函数($query,$params,$time,$conn){dd(数组($query,$params,$time,$conn));});这就像预期的那样工作,但是这仍然需要三行代码,为了简单起见,在代码中有没有一种方法可以将其缩短为一行?嗨,Marcin,我现在正在使用代码,但它似乎没有按照预期工作。我已尝试使用
->toSql()
函数调试并生成以下SQL:
从存在的“歌曲”中选择*(从“歌曲”所在的“主机”中选择*。“主机id”=“主机”。.id”和“跳过阈值”>歌曲。尝试次数和“活动”=?)和“下载”为空
。有什么想法吗?