Last Updated: February 25, 2016
·
3.416K
· pix-art

Silex Custom Constraint with DI

Earlier this week i wanted to implement ORM in my Silex-Skeleton. Since I was already using Forms and Validation I decided to create a custom constraint to validate if an Entity field is unique.
Dependency injection works a bit different in Silex compared to Symfony so i had to find a way to inject my EntityManager into my Validator.

So here are my steps

Step 1: Create your constraint

class Unique extends Constraint
{
    public $notUniqueMessage = '%string% has already been used.';
    public $entity;
    public $field;

    public function validatedBy()
    {
        return 'validator.unique';
    }
}

Step 2: Create your validator

We will inject the EntityManager via Setter injection later on in our ServiceProvider.

class UniqueValidator extends ConstraintValidator
{
    private $em;

    public function validate($value, Constraint $constraint)
    {
        $exists = $this->em
             ->getRepository($constraint->entity)
             ->findOneBy(array($constraint->field => $value));

        if ($exists) {
            $this->context->addViolation($constraint->notUniqueMessage, array('%string%' => $value));

            return false;
        }

        return true;
    }

    public function setEm(EntityManager $em)
    {
        $this->em = $em;
    }
}

Step 3: Create your ServiceProvider

This provider will help us create our validator and inject the EntityManager

class UniqueValidatorServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['validator.unique'] = $app->share(function ($app) {
            $validator =  new UniqueValidator();
            $validator->setEm($app['orm.em']);

            return $validator;
        });
    }

    public function boot(Application $app) {}
}

Step 4: Register your validator

$app->register(new Silex\Provider\ValidatorServiceProvider(), array(
    'validator.validator_service_ids' => array(
        'validator.unique' => 'validator.unique',
    )
));

All my tips have been moved to my blog www.pix-art.be so come check it out!

3 Responses
Add your response

I rewrote this since i made a miss judgement, Never doubt Fabien ;-) They had this implemented the correct way -> See step 4 code for the changed code

over 1 year ago ·

Can you share how to implement this in a Form Builder? Seems that there needs to be something else besides creating a new instance of the Validator.

over 1 year ago ·

When you create your form via FormFactory you can bind your entity to it. By using the magic "loadValidatorMetadata" inside your entity your "$form->isValid()" function will automatically validate your entity and map it with your form rows.

For more information and examples you can checkout my Silex-skeleton on Github. It contains loads of examples and best practices i use.

https://github.com/pix-art/Silex-Skeleton

over 1 year ago ·