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!
Written by Joeri Timmermans
Related protips
3 Responses
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
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.
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.