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 form fine. The entity has a relationship to status (N->1) which, when the status is changed from Unracked to Racked, needs to check for SSH and FTP access to the server. If access is not achieved, the validator should fail.
I have mapped a validator callback to the method isServerValid() within the Server entity as described here
http://symfony.com/doc/current/reference/constraints/Callback.html. I can obviously access the 'new' values via $this->status, but how can I get the original value?
In pseudo code, something like this:
public function isAuthorValid(ExecutionContextInterface $context)
{
    $original = ... ; // get old values
    if( $this->status !== $original->status && $this->status === 'Racked' && $original->status === 'Unracked' )
    {
        // check ftp and ssh connection
        // $context->addViolationAt('status', 'Unable to connect etc etc');
    }
}
Thanks in advance!
A complete example for Symfony 2.5 (http://symfony.com/doc/current/cookbook/validation/custom_constraint.html)
In this example, the new value for the field "integerField" of the entity "NoDecreasingInteger" must be higher of the stored value.
Creating the constraint:
// src/Acme/AcmeBundle/Validator/Constraints/IncrementOnly.php;
<?php
namespace Acme\AcmeBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
 * @Annotation
 */
class IncrementOnly extends Constraint
{
  public $message = 'The new value %new% is least than the old %old%';
  public function getTargets()
  {
    return self::CLASS_CONSTRAINT;
  }
  public function validatedBy()
  {
    return 'increment_only';
  }
}
Creating the constraint validator:
// src/Acme/AcmeBundle/Validator/Constraints/IncrementOnlyValidator.php
<?php
namespace Acme\AcmeBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Doctrine\ORM\EntityManager;
class IncrementOnlyValidator extends ConstraintValidator
{
  protected $em;
  public function __construct(EntityManager $em)
  {
    $this->em = $em;
  }
  public function validate($object, Constraint $constraint)
  {
    $new_value = $object->getIntegerField();
    $old_data = $this->em
      ->getUnitOfWork()
      ->getOriginalEntityData($object);
    // $old_data is empty if we create a new NoDecreasingInteger object.
    if (is_array($old_data) and !empty($old_data))
      {
        $old_value = $old_data['integerField'];
        if ($new_value < $old_value)
          {
            $this->context->buildViolation($constraint->message)
              ->setParameter("%new%", $new_value)
              ->setParameter('%old%', $old_value)
              ->addViolation();
          }
      }
  }
}
Binding the validator to entity:
// src/Acme/AcmeBundle/Resources/config/validator.yml
Acme\AcmeBundle\Entity\NoDecreasingInteger:
  constraints:
     - Acme\AcmeBundle\Validator\Constraints\IncrementOnly: ~
Injecting the EntityManager to IncrementOnlyValidator:
// src/Acme/AcmeBundle/Resources/config/services.yml
services:
   validator.increment_only:
        class: Acme\AcmeBundle\Validator\Constraints\IncrementOnlyValidator
        arguments: ["@doctrine.orm.entity_manager"]
        tags:
            - { name: validator.constraint_validator, alias: increment_only }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With