Laravel BelongsToMany关联syncWithoutDetaching返回updated异常问询
Laravel syncWithoutDetaching 同步含额外字段的多对多关联时updated数组行为解析
这个行为符合Laravel的预期设计。
原因在于,当使用syncWithoutDetaching(包括sync方法)处理带额外字段的多对多关联时,Laravel不会预先查询中间表现有记录的额外字段值并与传入值做对比判断。它的逻辑是:只要同步时为关联传入了额外字段数据,无论该字段值是否与现有记录一致,Laravel都会执行update语句更新中间表对应记录,因此对应的关联ID会被纳入返回的updated数组。
举个实际执行的例子:
$projectMedia->tags()->syncWithoutDetaching([ 1 => ['qty' => 5], 2 => ['qty' => 3] ]);
即便中间表中tag_id=1的记录qty已经是5,Laravel依然会执行update project_media_tag set qty = 5 where project_media_id = ? and tag_id = 1这类语句,所以tag_id=1会出现在updated数组内。
如果希望只有当额外字段值确实发生变化时,关联ID才进入updated数组,需要自行先查询现有中间表记录,对比字段值后仅传入需要更新的关联项,示例代码如下:
$existingTags = $projectMedia->tags()->withPivot('qty')->get()->keyBy('id'); $syncData = []; foreach ($yourTagData as $tagId => $data) { if (isset($existingTags[$tagId]) && $existingTags[$tagId]->pivot->qty == $data['qty']) { continue; // 值未变更,跳过更新 } $syncData[$tagId] = $data; } $result = $projectMedia->tags()->syncWithoutDetaching($syncData);
这样处理后,只有qty真正变化的tag_id才会出现在updated数组中。
内容的提问来源于stack exchange,提问作者Daniyal Nasir
相关产品推荐
相关产品推荐

