Search code examples
phpsymfonysymfony-formssymfony-validator

Symfony validation constraints annotations not working


I am trying to use annotations for Symfony form validation but I can't get it to work. No matter the constraint, the form always reports as valid. I am running on PHP 7.3 with doctrine/annotations 1.13, symfony/validator 5.1 and Symfony 5.1.5.

Here is the basic setup:

ProductionDependentCost.php

...
use Symfony\Component\Validator\Constraints as Assert;
...
    /**
     * @var float
     * @ORM\Column(type="float")
     * @Assert\NotNull
     * @Assert\Positive
     */
    private $costPerKW = 0;
...

ProductionDependentCostController.php

...
/**
     * @Route("/plant/{id}/productiondependentcosts", name="update_plant_production_dependent_costs", methods={"POST"})
     */
    public function updatePlantProductionDependentCosts(Plant $plant, Request $request): JsonResponse
    {
        $this->denyAccessUnlessGranted('view', $plant);
        $form = $this->createForm(ProductionDependentCostCollectionType::class, $plant, ['csrf_token_id' => 'vue-token']);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $this->em->flush();

            return $this->json('saved!');
        } elseif ($form->isSubmitted()) {
            return $this->json(ErrorUtil::parseErrors($form->getErrors(true)), Response::HTTP_BAD_REQUEST);
        }

        return $this->json('this should not be reached!', Response::HTTP_BAD_REQUEST);
    }
...

config/packages/framework.yaml

framework:
    ...
    validation:
      {
          enable_annotations: true
      }

I have many more annotation constraints but included only one in this example to not bloat the code snippet. No matter what I enter in the form (e.g -1000 for costPerKW), it will always return with 'saved!'. I have looked everywhere, but can't seem to find a solution. Really hope that someone knows the answer to this problem.

The form uses a CollectionType on a mapped collection field of Plant.php. The collection entries are entities of ProductionDependentCost.php and the corresponding FormType uses a simple mapped field for costPerKW.


Solution

  • I found the solution to my problem. Symfony Forms do not automatically validate entities inside collections. As my ProductionDependentCost is part of a collection inside my form, I have to add a "Valid" constraint to my collection field:

    Option 1:

    class Plant
    {
    ...
         /**
         * @var ProductionDependentCost[]|Collection
         * @ORM\OneToMany(targetEntity=ProductionDependentCost::class, mappedBy="plant", orphanRemoval=true, cascade={"persist",
         * "remove"})
         * @Assert\Valid
         */
        private $productionDependentCosts;
    ...
    }
    

    Option 2:

    class ProductionDependentCostCollectionType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('productionDependentCosts', CollectionType::class,
                [
                    ...
                    'constraints' => [
                        new Valid(),
                    ],
                ]);
        }
    
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => Plant::class,
            ]);
        }
    }
    

    This will validate every collection entity individually.