4

I've just moved to symfony 5 and baffled! I've done this same thing with validators many times with Symfony 4, but now dependency injection of EntityManagerInterface into a custom validator produces this error:

Too few arguments to function App\Validator\Constraints\UserUsernameConstraintValidator::__construct(), 0 passed in /var/www/appbaseV4/vendor/symfony/validator/ContainerConstraintValidatorFactory.php on line 52 and exactly 1 expected

The validator class is as follows:

<?php

namespace App\Validator\Constraints;

use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UserUsernameConstraintValidator extends ConstraintValidator
{

    /**
     * @var EntityManagerInterface
     */
    private $em;

    /**
     * UserEmailValidator constructor.
     * @param EntityManagerInterface $entityManager
     */
    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->em = $entityManager;

    }

    /**
     * @param mixed $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint) : void
    {


        if(!$constraint instanceof UserUsernameConstraint){
            throw new UnexpectedTypeException($constraint,UserUsernameConstraint::class);
        }

        if(null === $value || '' === $value){
            return;
        }

        if($value != $constraint->value){
            /** @var UserRepository $repo */
            $repo = $this->em->getRepository(User::class);

            if($repo->findOneBy(['username'=>$value])){
                $this->context->buildViolation($constraint->errorMessage)->setParameter('username',$value)->addViolation();
            }
        }

    }
}

And then using it in the form type as i always do:

$builder
            ->add('username',TextType::class,[
                'attr'=>[
                    'class'=>'form-control'
                ],
                'required'=>true,
                'constraints'=>[
                    new UserUsernameConstraint(),
                    new Length([
                        'min'=>6,
                        'max'=>20
                    ]),

                ]
            ])

What's going on here? Have they changed this in Symfony 5 because it's just not injecting the entity manager like it normally does when i use symfony 4.

Glen Elkins
  • 867
  • 9
  • 30
  • 1
    It sounds like the container isn't aware of your validator - [line 52 in the source](https://github.com/symfony/validator/blob/master/ContainerConstraintValidatorFactory.php) is the code-path where `$container->has(...)` returned false. You might need to tweak your service configuration - I thought ConstraintValidators were picked up by default, but you might have a slightly different setup – iainn Apr 14 '20 at 14:14
  • @iainn that's what i mean, they usually are picked up by default, always has been in symfony 4 and according to their 5 documentation it still should be as i am using the default services.yaml config – Glen Elkins Apr 14 '20 at 14:16
  • I made a quick test case in a fresh S5 project and your constraint works as expected. There is something amiss in your upgrade process. Maybe try: "bin/console debug:container UserUsernameConstraintValidator" and verify you have the service defined. – Cerad Apr 14 '20 at 16:32
  • And off-topic but you should be throwing Symfony\Component\Validator\Exception\UnexpectedTypeException and not the Form exception. – Cerad Apr 14 '20 at 16:36
  • 1
    cleared the cache? – craigh Apr 14 '20 at 22:50
  • Thanks for the answers, I’ll give clearing the cache a try. There shouldn’t be anything missing as it’s all setup for auto wire which works everywhere else. If I have to I’ll rebuild the entire validation. – Glen Elkins Apr 15 '20 at 15:29
  • 1
    By the looks of it Symfony is not picking up your validator correctly. I bet it will be autowiring. Are you sure it's not excluding Validators? Also do you have corresponding constraint file for the validator? Also like someone has mentioned here it would be good to run `debug: container`. I am 100% sure Symfony 5 should pick it up automatically because it works with my Validators. Check for typos as well. – Robert May 09 '20 at 07:19

1 Answers1

1

It seems that you are not using the default services.yaml configuration, in this case you have to tag your constraint validator with the validator.constraint_validator tag. Check the documentation for Constraint Validators with Dependencies or fix/update your Automatic Service Loading in config/services.yaml.

Thomas Baier
  • 434
  • 3
  • 8