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。
还有一个关于如何使用它的具体示例,包括 Post
、Country
和 User
,但我认为足以给您提示如何使用在 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;
});
我正在学习 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。
还有一个关于如何使用它的具体示例,包括 Post
、Country
和 User
,但我认为足以给您提示如何使用在 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;
});