Symfony DI injects an empty array instead of entity manager object

563 Views Asked by At

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?

1

There are 1 best solutions below

0
dchesterton On BEST ANSWER

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.