为什么Laravel 7中多对多关联pivot使用sync方法无法正常写入数据?
问题原因
sync与attach的参数规则完全不同:attach($关联ID, $pivot字段数组)的写法是符合方法定义的,但是sync的第一个参数要求传入需要保留的所有关联ID数组,第二个参数为布尔值,控制是否删除不在传入列表里的旧关联,默认值为true。你原代码中将pivot数组作为sync的第二个参数传入,会被直接识别为布尔值true,pivot字段完全不会被处理。- 循环调用
sync的逻辑存在冲突:
每次调用sync时,默认会先清空所有不在当前传入ID列表里的旧关联,你循环中每次仅传入单个关联ID,前一次循环写入的关联会被后一次循环直接删除,最终要么仅保留最后一条关联,要么因为参数错误完全没有数据写入。
正确解决方法
首先需要按照sync的参数要求,先构造好关联ID与对应pivot字段的映射数组,不要在循环内调用关联操作方法。根据业务场景可选择以下两种方案:
方案1:保留现有关联,仅新增/更新本次提交的关联(等价于原attach的业务效果)
使用syncWithoutDetaching方法,该方法不会删除未在本次提交中的旧关联:
if ($request->link) { $syncData = []; foreach($request->name as $key => $social){ $syncData[$social] = ['value' => $request->link[$key] ?? null]; } $stall->socials()->syncWithoutDetaching($syncData); }
方案2:清空旧关联,仅保留本次提交的关联
使用原生sync方法,自动删除不在本次提交列表中的所有旧关联:
if ($request->link) { $syncData = []; foreach($request->name as $key => $social){ $syncData[$social] = ['value' => $request->link[$key] ?? null]; } $stall->socials()->sync($syncData); }
如果仅需要修改已存在关联的pivot字段值,不需要新增关联,可使用updateExistingPivot方法:
$stall->socials()->updateExistingPivot($socialId, ['value' => $新的pivot值]);
内容的提问来源于stack exchange,提问作者user17301916
相关产品推荐
相关产品推荐

