我有 3 个模型:
Match
Team
Player
我想创建一个具有以下结构的表:
id | match_id | team_id | player_id
这样我就可以将我引用的 3 个模型联系起来。
我为我提到的表创建了第 4 个模型MatchPlayers
,我可以毫无问题地使用"搜索"功能。喜欢这个:
$match->matchPlayers()->first()->team()->get()
它返回结果,但我无法执行
$match->matchPlayers()->sync([])
那么,我应该如何解决这个问题呢?我的关系是错误的还是 3 模型关系不允许同步方法,而我应该使用其他方法?
提前致谢
编辑:
Match.php
public function teamPlayers(){
return $this->hasMany('ModulesMatchsEntitiesMatchPlayer');
}
Team.php
public function matchTeamPlayers(){
return $this->hasMany('ModulesMatchsEntitiesMatchPlayer');
}
Player.php
public function matchTeamPlayers(){
return $this->hasMany('ModulesMatchsEntitiesMatchPlayer');
}
MatchPlayer.php
public function player(){
return $this->belongsTo('ModulesPlayersEntitiesPlayer');
}
public function match(){
return $this->belongsTo('ModulesMatchsEntitiesMatch');
}
public function team(){
return $this->belongsTo('ModulesTeamsEntitiesTeam');
}
如果您已经按照此处找到的数据透视表和多对多关系的Laravel文档进行操作,并且它仍然不起作用,那么"Attach"可能会更幸运。例如;
$matchPlayer = MatchPlayer::create([...]);
$match->matchPlayers()->attach($matchPlayer)
可以在此处找到同步与附加的一个很好的例子
对这种关系使用第四个模型是有意义的,因为它为您提供了数据透视表上第三个关系的导航属性。这样,您可以通过这种方式形成更复杂的查询。
对于您的特定问题,基于match_id
和team_id
进行同步,我只会做这样的事情:
$matchId = 123;
$teamId = 234;
$rows = [
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 345],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 346],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 347],
];
// remove all previously stored connections
MatchPlayer::where('match_id', $matchId)
->where('team_id', $teamId)
->delete();
// insert the news ones
// (you could also use MatchPlayer::create() per item or
// $matchPlayer->save(), it doesn't matter)
MatchPlayer::insert($rows);
如果此操作非常频繁地发生,则可能会烧毁数据透视表的大量id
值。在这种情况下,您还可以执行更高效的同步,这稍微复杂一些:
$matchId = 123;
$teamId = 234;
$rows = [
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 345],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 346],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 347],
];
// delete all players that are not among the new data anymore
MatchPlayer::where('match_id', $matchId)
->where('team_id', $teamId)
->whereNotIn('player_id', array_pluck($rows, 'player_id'))
->delete();
// remove rows from new data that already exist
$exist = MatchPlayer::where('match_id', $matchId)
->where('team_id', $teamId)
->pluck('player_id')
->toArray();
$rows = array_filter($rows, function ($value, $key) use ($exist) {
return ! in_array($value['player_id'], $exist);
});
// then we store the remaining data
MatchPlayer::insert($rows);