php - Laravel Eloquent 关系 - 表的多列引用相同的外键
问题描述
Laravel/Eloquent 新手在这里。我正在实现一个简单的棋盘游戏。每场比赛有4名玩家。表结构由一个 Players 表和一个 Games 表组成:
SELECT * FROM players;
id | name |
---------------------
1 | John |
2 | Mary |
3 | Linda |
4 | Alex |
5 | Chris |
6 | Ron |
7 | Dave |
SELECT * FROM games;
id | player1_id | player2_id | player3_id player4_id
---------------------------------------------------------------------
1 | 1 | 2 | 3 | 4
2 | 3 | 5 | 6 | 7
3 | 2 | 3 | 5 | 6
4 | 2 | 4 | 5 | 7
目标:我希望能够获得玩家参与过的所有游戏。
为此,我试图games()
在 Player 模型中编写一个函数。对于 id 2 的玩家,这应该返回游戏 1、3、4 / 对于 id 3 的玩家,它应该返回游戏 1、2、3 等等。
使用原始 SQL 我会做这样的事情:
SELECT * FROM games WHERE
(player1_id = 2 OR player2_id = 2 OR player3_id = 2 OR player4_id = 2)
但是对于 Eloquent,我很难弄清楚必须如何建立这种关系才能实现这一目标。
同样,我也希望能够做相反的事情——返回一个游戏的所有玩家——players()
在Game
模型中使用一个函数。
型号:
// Models/Player.php
//...
class Player extends Model
{
public function games(){
//?
}
}
// Models/Game.php
//...
class Game extends Model
{
public function players(){
//?
}
}
解决方案
在不更改数据库结构的情况下,您可能会滥用声明hasMany
来获取所有 4 个玩家。
class Game extends Model
{
public function players()
{
return $this->hasMany(Player::class, 'id', 'player1_id')
->orWhere('id', $this->player2_id)
->orWhere('id', $this->player3_id)
->orWhere('id', $this->player4_id);
}
}
class Player extends Model
{
public function games()
{
return $this->hasMany(Game::class, 'player1_id', 'id')
->orWhere('player2_id', $this->id)
->orWhere('player3_id', $this->id)
->orWhere('player4_id', $this->id);
}
}
然而,这并不理想。
您应该有第三个表来正确映射这种多对多关系。
table 1 - players: id (pk), name
table 2 - games: id (pk)
table 3 - game_player: id (pk), game_id (fk), player_id (fk), unique([game_id, player_id])
class Game extends Model
{
public function players()
{
return $this->belongsToMany(Player::class, 'game_player');
}
}
class Player extends Model
{
public function games()
{
return $this->belongsToMany(Game::class, 'game_player');
}
}
推荐阅读
- python - 嵌套列表python中的单词
- facebook - Facebook Instant Games:奖励视频无法预加载:客户端不支持消息:getrewardedvideoasync
- scala - 如何在字符串中第 n 次出现分隔符之前删除所有数据?
- python - 在另一个类中使用实例方法作为装饰器
- jpa - 如果父级不存在,弹簧数据保存只会创建级联子级
- groovy-eclipse - 在 Eclipse IDE (Oxygen) 上为 Eclipse 提交者安装 groovy-eclipse 时出现 code=10053 错误
- python - 在for循环python中编码和保存多个数组
- javascript - 在 Node.JS/NPM 的 MySQL 库中使用 Promise 和查询
- processing - 处理 3.3.7 draw() 停止循环
- java - Java 模块:Mockito 2.20.0 的可访问性问题