Symfony2 Form Validator - Comparing old and new values before flush

前端 未结 4 626
暗喜
暗喜 2021-02-05 10:40

I was wondering if there is a way to compare old and new values in a validator within an entity prior to a flush.

I have a Server entity which renders to a

4条回答
  •  Happy的楠姐
    2021-02-05 11:11

    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 
    {
    

提交回复
热议问题