Symfony 2.6实体更新问题:执行操作时新增而非更新行
解决Symfony 2.6实体更新总是插入新行的问题
看起来你遇到的核心问题是:转换器返回的是全新的实体实例,而不是数据库中已存在的实体对象,导致EntityManager认为这是新数据,执行了INSERT而非UPDATE操作。我给你梳理几个关键的解决步骤:
1. 确保表单绑定到现有实体(编辑场景)
在构建编辑表单时,一定要先从数据库中取出要更新的实体,再传递给表单,而不是直接创建新实体:
// 控制器中的编辑动作示例 $indicatorId = $request->get('id'); $indicatorModel = $this->em->getRepository(IndicatorModel::class)->find($indicatorId); // 绑定现有实体到表单 $form = $this->createForm(IndicatorModelType::class, $indicatorModel); $form->handleRequest($request);
这一步是基础,表单需要知道它要操作的是已存在的实体,后续提交后才能正确触发更新逻辑。
2. 修正转换器的transform方法逻辑
你的转换器现在应该是每次都新建实体,改成根据ID加载现有实体并更新属性:
public function transform($formData) { // 从表单数据中获取实体ID(表单需要传递这个值) $entityId = $formData['id'] ?? null; if ($entityId) { // 加载数据库中已存在的实体 $indicatorModel = $this->em->getRepository(IndicatorModel::class)->find($entityId); if (!$indicatorModel) { throw new \RuntimeException("IndicatorModel with ID {$entityId} not found"); } } else { // 只有新增场景才创建新实体 $indicatorModel = new IndicatorModel(); } // 用表单数据更新实体属性 $indicatorModel->setName($formData['name']); $indicatorModel->setDescription($formData['description']); // ... 其他需要更新的属性 return $indicatorModel; }
这里的关键是:编辑时复用数据库中已有的实体对象,而不是每次都新建。
3. 在表单中添加隐藏的ID字段
要让转换器能拿到实体ID,需要在表单类型中添加一个隐藏字段来传递ID:
// 你的表单类 IndicatorModelType public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('id', HiddenType::class) // 隐藏字段传递实体ID ->add('name', TextType::class) ->add('description', TextareaType::class) // ... 其他业务字段 ; }
这样表单提交时,ID会被包含在$createIndicatorModelFormModel数组中,转换器就能定位到要更新的实体了。
4. 优化onSuccess方法的持久化逻辑
如果转换器返回的是EntityManager已管理的实体(从find方法加载的),其实不需要调用persist,直接flush就会触发更新:
public function onSuccess($createIndicatorModelFormModel) { $indicatorModel = $this->indicatorModelTransformer->transform($createIndicatorModelFormModel); // 如果是已管理的实体,persist可以省略 // $this->em->persist($indicatorModel); $this->em->flush(); }
如果你的实体是脱管状态(比如序列化后反序列化的),可以用merge来让EntityManager重新管理它:
$managedEntity = $this->em->merge($indicatorModel); $this->em->flush();
内容的提问来源于stack exchange,提问作者DavidDG
相关产品推荐
相关产品推荐

