嵌套foreach遍历修改数据时字段全被覆盖为单一值的解决方案
问题根因
你的双层循环逻辑存在本质错误:
- 外层每遍历到一个查询返回的School实体对象,内层就会把
$data['school']里的所有键值对依次set到这同一个对象上,一轮内层循环结束后,该对象的key、value属性永远会被内层循环最后一次迭代的值覆盖 - 整个逻辑没有做「实体原有key和传入更新值的key匹配」判断,不管数据库查出来的实体本身key是什么,都会被无差别覆盖,最终所有实体属性完全一致,和你遇到的全被覆盖为同一个值的现象完全吻合。
修复方案
去掉无意义的全量内层循环,遍历数据库查询结果时,先获取当前实体自身的key,只在传入的更新数据中存在对应key的匹配项时才做赋值操作。
修复后的代码如下:
$entityManager = $this->doctrine->getManager(); $schoolRepository = $this->em->getRepository(School::class); $schoolList = $schoolRepository->findBy(['id' => $data['session']['id']]); if (!empty($schoolList)) { foreach ($schoolList as $school) { $currentKey = $school->getKey(); // 仅匹配当前实体key对应的更新值,不做全量循环覆盖 if (isset($data['school'][$currentKey])) { $school->setId($data['session']['id']); $school->setValue($data['school'][$currentKey]); } } $entityManager->flush(); // 所有赋值完成后统一持久化到数据库 }
注意事项
findBy()方法返回值永远是数组类型,无匹配结果时返回空数组,不会返回null,判断查询结果是否非空用empty()比!== null更严谨- 你的业务逻辑是按原有key匹配更新对应value,不需要调用
setKey()修改key字段,多余的setKey调用反而可能把原有key改乱 - 所有实体属性修改完成后,必须调用实体管理器的
flush()方法,修改才会被持久化同步到数据库,否则赋值操作只在内存中生效,不会落库
内容的提问来源于stack exchange,提问作者Curtis Lanz
相关产品推荐
相关产品推荐

