0

I am trying to inject an entity manager object intro my validation class however Symfony DI injects a empty array(tested with var_dump). I can't understand why this is not working. Here goes some of my code.

app/config.yml

services:
    unique_booking_date_validator:
        class: MyCompany\Bundle\AppBundle\Domain\Validator\UniqueBookingDate
        arguments:
            - "@doctrine.orm.entity_manager"
        tags:
            - { name: validator.constraint_validator, alias: unique_booking_date }

My class

namespace MyCompany\Bundle\AppBundle\Domain\Validator;

use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Constraint;

/** @Annotation */
class UniqueBookingDate extends Constraint
{
    protected $em;

    public function __construct(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }
    public function validatedBy()
    {
        return 'unique_booking_date';
    }

    ...
}

It returns this exception:

Catchable Fatal Error: Argument 1 passed to MyCompany\Bundle\AppBundle\Domain\Validator
\UniqueBookingDate::__construct() must be an instance of Doctrine\ORM\EntityManager, 
array given, called in C:\htdocs\booking-manager\vendor\doctrine\annotations\lib\Doctrine\
Common\Annotations\DocParser.php on line 794 and defined in C:\htdocs\booking-manager
\src\MyCompany\Bundle\AppBundle\Domain\Validator\UniqueBookingDate.php line 20

I am running Symfony v2.5.7. Is anything wrong with the code?

dextervip
  • 4,999
  • 16
  • 65
  • 93
  • And what if you extend `UniqueBookingDate` with `ConstraintValidator`? – Damaged Organic Nov 21 '14 at 08:30
  • @Grimv01k I still have the same issue. Seems the validator.constraint_validator tag is not registering my custom validator properly because I am able to get the service by id having entity manager injected. – dextervip Nov 21 '14 at 08:41
  • Looks like you are indeed passing an empty array via services.yml. I'll try to reproduce, but maybe defining orm like `arguments: [@doctrine.orm.entity_manager]` will do something? – Damaged Organic Nov 21 '14 at 08:45
  • @Grimv01k Still have the same issue. – dextervip Nov 21 '14 at 09:56
  • 1
    Just finished this tutorial: http://knpuniversity.com/screencast/question-answer-day/custom-validation-property-path#applying-the-validation-logic, section `Applying the Validation Logic` has such EM injection, and it works fine. Maybe will give you a hint... From what I could see it should be one class that extends `Constraint` and one that of `ConstraintValidator`, in which EM is passed, and your `tags` also expecting `validator.constraint_validator`. If fatal says array is empty, than probably injection in `config.yml` is omitted. I hope this will be of any help to you. – Damaged Organic Nov 21 '14 at 11:44
  • @Grimv01k Sorry my mistake, I didn't split the class as shown in the tutorial. Thank you :) – dextervip Nov 21 '14 at 19:26

1 Answers1

1

This fails because Symfony is passing the options array expected by the parent Constraint class.

You need to split your validator into two classes: one annotation class, and one that does the actual validation.

/** @Annotation */
class UniqueBookingDate extends Constraint
{
    public function validatedBy()
    {
        return 'unique_booking_date_validator';
    }
}

Now set up a service called unique_booking_date_validator, which does the actual validation. Here you can pass the entity manager and any other dependencies.

class UniqueBookingDateValidator extends ConstraintValidator
{
    protected $em;

    public function __construct(\Doctrine\ORM\EntityManager $em)
    {
        $this->em = $em;
    }

    public function validate($value, Constraint $constraint)
    {
        // do validation here
    }
}

So your services.yml file should look something like this:

services:
    unique_booking_date_validator:
        class: MyCompany\Bundle\AppBundle\Domain\Validator\UniqueBookingDateValidator
        tags:
            - { name: validator.constraint_validator, alias: unique_booking_date_validator }
        arguments:
            - "@doctrine.orm.entity_manager"

For a good example of this in action, check out Symfony's UniqueEntity validator, or take a look at Symfony's Cookbook article.

dchesterton
  • 2,070
  • 1
  • 14
  • 13