Php 如何在3模型关系上使用同步?-拉维尔

Php 如何在3模型关系上使用同步?-拉维尔,php,laravel,laravel-5,eloquent,Php,Laravel,Laravel 5,Eloquent,我有3种型号: 比赛球队球员 我想创建一个具有以下结构的表: id | match_id | team_id | player_id 这样我就可以把我提到的3个模型联系起来 我为我提到的表创建了第四个模型MatchPlayers,我可以毫无问题地使用“搜索”功能。像这样: $match->matchPlayers()->first()->team()->get() 它会返回预期的结果,但我不能做任何更改 $match->matchPlayers()->s

我有3种型号:

比赛
球队
球员

我想创建一个具有以下结构的表:

id | match_id | team_id | player_id
这样我就可以把我提到的3个模型联系起来

我为我提到的表创建了第四个模型
MatchPlayers
,我可以毫无问题地使用“搜索”功能。像这样:

$match->matchPlayers()->first()->team()->get() 
它会返回预期的结果,但我不能做任何更改

$match->matchPlayers()->sync([])
那么,我应该如何解决这个问题呢?是我的关系错误还是3模型关系不允许使用同步方法,我应该使用其他方法

提前谢谢


编辑:


如果您已经遵循了关于透视表和许多关系的Laravel文档,但它仍然不起作用,那么使用“附加”可能会更幸运。比如,

$matchPlayer = MatchPlayer::create([...]);

$match->matchPlayers()->attach($matchPlayer)

sync vs attach的一个很好的例子是使用第四个模型来处理这种关系,因为它为透视表上的第三个关系提供了导航属性。通过这种方式,您可以通过这种方式形成更复杂的查询

对于您的特定问题,基于
match\u id
team\u 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);

同步和附加返回为“不存在”。我在主主题中添加了我的模型结构/关系,请看。
sync()
hasmall
关系中不可用。也许你能准确地解释你的目标是什么,然后我们可以建议如何去做。(BTW,我认为你目前的关系设计是正确的。所以这不是问题。)我的目标是能够发送MatCHYID、TeaSyID和一个播放器数组(PraveRoID)并插入这些记录。而且,如果存在match_id、team_id和不在数组中的玩家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);