laravel Eloquent 关系查询范围

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36512060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 13:34:29  来源:igfitidea点击:

Eloquent Query Scope on Relationships

phplaraveleloquent

提问by InvalidSyntax

I have two models, App\Song (belongsTo App\Host) and App\Host (hasMany App\Song).

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

I have the following query in my Controller:

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

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

For reusability I would like to turn into a query scope(s).

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

I'm quite new to Eloquent so I'm not sure this is the correct way to do this being that its two Models as its not returning any results (where there should be).

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

Song.php

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

回答by Marcin Nabia?ek

You should put scopes into Models they belong to. Looking at your initial query scopes scopeEligableand scopeActiveHostbelongs to Hostmodel, so you should move them into Hostmodel and then you'll be able to use your query using scopes like this:

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

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

and as already pointed in comment you should add returnto each scope so they could be used as they intended.

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

EDIT

编辑

If you would like to make using it shorter, you could create new relationship in Songmodel:

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

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

so now, you could write:

所以现在,你可以写:

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

回答by trinvh

I think you're mistaken about 2 models. I think this should work

我认为您对 2 个模型有误解。我认为这应该有效

Song.php

歌曲.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();