You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:33:28