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

1

1

I have a project entity which has many images, every image has title, imageFile attributes

I want the user to be able to add, update and delete images from the project form.

The problem is that the projectImage entity validation groups when it is new should be different from when it is being edited.

and this is the code

ProjectType

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';
    }
}

as you can see in the ProjectImageType I'm adding a validation group "newImage" if the image is new or if the user want to add new image, in this case only the image file should be required and should not be required if the user want to just update the title of the image.

the problem is that validation group "newImage" which I'm adding in the ProjectImageType always ignored.

I tried the solution provided here Specify different validation groups for each item of a collection in Symfony 2? but the problem is that the cascade_validation option removed from symfony 3

the question here is how can can validate every collection type entity against different validation groups from each other and also different from the parent form type validation groups?

Masque answered 13/10, 2017 at 9:33 Comment(0)
M
3

I resolved the problem without using validation groups by adding a callback validation in the project entity as following:

ProjectImage Entity

/**
 * 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();
    }
}
Masque answered 16/10, 2017 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.