Laravel - Eloquent 关系 whereHas 一个或多个其他关系

Laravel - Eloquent relation whereHas one or more other relations

我正在学习 Laravel 和 Laravel eloquent,现在我尝试使用 Laravel 中的关系来解决问题。 这是我要归档的内容:

该数据库拥有许多体育俱乐部。体育俱乐部有很多球队。每个队都有比赛。团队 table 有一个名为 club_id 的列。现在我想创建 Eloquent 关系来获取俱乐部的所有比赛。

这是我目前得到的:

俱乐部模式

id => PRIMARY

public function games()
    {
        return $this->hasMany('App\Models\Games')->whereHas('homeTeam')->orWhereHas('guestTeam');
    }

游戏模型

home_id => FOREIGN KEY of team ; guest_id => FOREIGN KEY of team

public function homeTeam()
    {
        return $this->belongsTo('App\Models\Team','home_id')->where('club_id','=', $club_id);
    }

    public function guestTeam()
    {
        return $this->belongsTo('App\Models\Team','guest_id')->where('club_id','=', $club_id);
    }

团队模型

id => PRIMARY ; club_id => FOREIGN

在我的控制器中,我只想Club::findOrFail($id)->games()

执行上面的代码 returns 一个 SQL 游戏 table 没有名为 club_id 的列的错误。

建立这种关系的正确方法是什么?

谢谢!

编辑

感谢 Nikola Gavric,我找到了获得所有比赛的方法 - 但仅限于俱乐部球队是主队或客队的情况。

关系如下:

public function games()
    {
        return $this->hasManyThrough('App\Models\Game','App\Models\Team','club_id','home_id');
    }

如何获得 home_id 或 guest_id 匹配俱乐部球队的比赛?此函数中的最后一个参数不允许数组。

当您定义俱乐部 hasMany 游戏时,您表示该游戏有一个名为 club_id 的外键指向俱乐部。 belongsTo 是相同的,但方式不同。这些需要与数据库中的内容保持一致,这意味着您需要将这些键定义为表中的外键。

试试这个...

俱乐部模式

public function games()
    {
        return $this->hasMany('App\Models\Games');
    }

游戏模型

public function homeTeam()
    {
        return $this->belongsTo('App\Models\Team','home_id');
    }

    public function guestTeam()
    {
        return $this->belongsTo('App\Models\Team','guest_id');
    }

你的查询喜欢

Club::where('id',$id)->has('games.guestTeam')->get();

有一种检索 "distant relationship with an intermediary" 的方法,它被称为 Has Many Through

还有一个关于如何使用它的具体示例,包括 PostCountryUser,但我认为足以给您提示如何使用在 Club 模型中创建 games 关系。 Here 是一个 link,但是当你打开它时,搜索 hasManyThrough 关键字,你会看到一个例子。

P.S:使用正确的 keys naming 你可以通过以下方式实现它:

public function games()
{
    return $this->hasManyThrough('App\Models\Games', 'App\Models\Teams');
}

编辑#01

由于您有 2 种类型的团队,因此您可以创建 2 种不同的关系,每种关系都会为您提供所需的一种类型。像这样:

public function gamesAsHome()
{
    return $this
        ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'home_id');
}

public function gamesAsGuests()
{
    return $this
        ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'guest_id');
}

编辑#02

合并关系:要合并这两个关系,您可以在Collection实例上使用merge()方法,它将做的是,它将将第二个集合中的所有记录附加到第一个

$gamesHome = $model->gamesAsHome;
$gamesGuests = $model->gamesAsGuests;
$games = $gamesHome->merge($gamesGuests);

return $games->unique()->all();

感谢@HCK 指出合并后您可能有重复项,需要 unique() 才能在合并后获得 独特的游戏


编辑#03

Collection 包含 numerical indexing 的情况下,

sortBy 还提供 callable 而不是 attribute name。您可以这样对 Collection 进行排序:

$merged->sortBy(function($game, $key) {
    return $game->created_at;
});