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

时间:2017-10-13 09:33:55

标签: symfony symfony-forms symfony-3.3

我有一个项目实体,它有很多图像,每个图像都有标题,imageFile属性

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

问题是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"如果图像是新的或用户想要添加新图像,在这种情况下,只需要图像文件,如果用户只想更新图像的标题,则不需要图像文件。

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

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

这里的问题是如何能够针对不同的验证组相互验证每个集合类型实体,并且还与父表单类型验证组不同?

1 个答案:

答案 0 :(得分:3)

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

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();
    }
}