在 Symfony 3 中为 collection 的每个项目指定不同的验证组?

Specify different validation groups for each item of a collection in Symfony 3?

我有一个包含很多图像的项目实体,每个图像都有标题、图像文件属性

我希望用户能够从项目表单中添加、更新和删除图像。

问题是 projectImage 实体验证组在新建时应该与编辑时不同。

这是代码

项目类型

class ProjectType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->addEventSubscriber(new \ControlPanelBundle\Form\EventListener\CityFieldSubscriber())
            ->addEventSubscriber(new \ControlPanelBundle\Form\EventListener\CountryFieldSubscriber());

        $builder
            ->add('title')
            ->add('description')
            ->add('area')
            ->add('startDate')
            ->add('deliveryDate')
            ->add('phases')
            ->add('partners', EntityType::class, [
                'class'         => 'AppBundle:Partner',
                'multiple'      => true,
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('p')
                        ->orderBy('p.title', 'ASC');
                }
            ])
            ->add('projectImages', CollectionType::class, [
                'entry_type'     => ProjectImageType::class,
                'allow_add'      => true,
                'allow_delete'   => true,
                'delete_empty'   => true,
                'by_reference'   => false,
                'error_bubbling' => false
        ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Project'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'project';
    }
}

ProjectImageType

class ProjectImageType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', HiddenType::class)
            ->add('title', TextType::class)
            ->add('type', ChoiceType::class, ['choices' => array_flip(\AppBundle\Entity\ProjectImage::getTypeChoices())])
            ->add('imageFile', FileType::class);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class'        => 'AppBundle\Entity\ProjectImage',
            'validation_groups' => function(\Symfony\Component\Form\FormInterface $form) {
                $validationGroups = ['Default'];

                if ($form->getData() === null || null === $form->getData()->getId()) {
                    $validationGroups[] = "newImage";
                }

                return $validationGroups;
            }
        ]);
    }

    public function getName()
    {
        return 'project_image';
    }
}

如您在 ProjectImageType 中所见,我正在添加验证组 "newImage" 如果图像是新图像或用户想要添加新图像,在这种情况下,只需要图像文件,并且如果用户只想更新图像的标题,则不需要。

问题是我在 ProjectImageType 中添加的验证组 "newImage" 总是被忽略。

我尝试了此处提供的解决方案 Specify different validation groups for each item of a collection in Symfony 2? 但问题是 cascade_validation 选项从 symfony 3

中删除

这里的问题是如何针对不同的验证组验证每个 collection 类型的实体,并且也不同于 parent 表单类型验证组?

我在不使用验证组的情况下通过在项目实体中添加回调验证解决了问题,如下所示:

ProjectImage 实体

/**
 * assert that image not blank only if new object
 *
 * @Assert\Callback
 */
public function validateImage(ExecutionContextInterface $context) {
    if (null === $this->id && null === $this->getImageFile()) {
        $context->buildViolation('Image is required')
                ->atPath('imageFile')
                ->addViolation();
    }
}