Symfony表单预设集合仅保存非空WeekDay实例的问题求解
解决方案
你只需要在表单数据绑定完成后、持久化到数据库前,过滤掉符合空规则的WeekDay实例即可,因为你的Week实体对days关联配置了orphanRemoval=true,被移除的空实例不会被持久化,原有已保存的空实例也会自动删除。
步骤1:确定空WeekDay的判断规则
根据你的业务场景自定义空实例的判定条件,示例规则如下(可自行调整):
used字段为false- 关联的
themes为空 preparations配置为空
步骤2:添加表单事件过滤空实例
修改WeekType的buildForm方法,新增POST_SUBMIT事件监听,在表单数据完全绑定后移除空的WeekDay:
public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name') ->add('days', CollectionType::class, [ 'entry_type' => WeekDayType::class, 'by_reference' => false, 'allow_add' => true, 'allow_delete' => true, 'data' => $this->service->getAllSortedDays($builder->getData()), ]) ; // 原有的SUBMIT事件保留,用来解决校验失败后展示不全的问题 $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) { $form = $event->getForm(); $data = $event->getForm()->getData(); $form ->add('days', CollectionType::class, [ 'entry_type' => WeekDayType::class, 'by_reference' => false, 'allow_add' => true, 'allow_delete' => true, 'data' => $this->service->getAllSortedDays($data), ]) ; }); // 新增POST_SUBMIT事件过滤空WeekDay $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { /** @var Week $week */ $week = $event->getData(); foreach ($week->getDays() as $day) { // 此处判断规则可根据业务自行修改 if ( !$day->isUsed() && $day->getThemes()->isEmpty() && empty($day->getPreparations()) ) { $week->removeDay($day); } } }); }
可选方案:控制器层面过滤
如果你不想在表单类里加逻辑,也可以在处理表单提交的控制器中,校验通过后、执行flush前手动过滤:
// 控制器中处理表单的代码示例 $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { /** @var Week $week */ $week = $form->getData(); // 过滤空WeekDay foreach ($week->getDays() as $day) { if ( !$day->isUsed() && $day->getThemes()->isEmpty() && empty($day->getPreparations()) ) { $week->removeDay($day); } } $entityManager->flush(); // 后续逻辑... }
内容的提问来源于stack exchange,提问作者Atyz
相关产品推荐
相关产品推荐

