Accessing the EntityManager inside a custom validator in symfony2
you could check for the previous value inside your controller action ... but that would not really be a clean solution!
normal form-validation will only access the data bound to the form ... no "previous" data accessible by default.
The callback constraint you're trying to use does not have access to the container or any other service ... therefore you cant easily access the entity-manager (or whatever previous-data provider) to check for the previous value.
What you need is a custom validator on class level. class-level is needed because you need to access the whole object not only a single value if you want to fetch the entity.
The validator itself might look like this:
namespace Vendor\YourBundle\Validation\Constraints;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class StatusValidator extends ConstraintValidator
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function validate($status, Constraint $constraint)
{
$em = $this->container->get('doctrine')->getEntityManager('default');
$previousStatus = $em->getRepository('YourBundle:Status')->findOneBy(array('id' => $status->getId()));
// ... do something with the previous status here
if ( $previousStatus->getValue() != $status->getValue() ) {
$this->context->addViolationAt('whatever', $constraint->message, array(), null);
}
}
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
public function validatedBy()
{
return 'previous_value';
}
}
... afterwards register the validator as a service and tag it as validator
services:
validator.previous_value:
class: Vendor\YourBundle\Validation\Constraints\StatusValidator
# example! better inject only the services you need ...
# i.e. ... @doctrine.orm.entity_manager
arguments: [ @service_container ]
tags:
- { name: validator.constraint_validator, alias: previous_value }
finally use the constraint for your status entity ( i.e. using annotations )
use Vendor\YourBundle\Validation\Constraints as MyValidation;
/**
* @MyValidation\StatusValidator
*/
class Status
{