4

I need to be able to do complex custom validation of an entire entity in Symfony2.

Eg: my entity has many subentities, and all subentities must sum to 100.

As far as I can fathom, Symfony2 validators only validate singular fields?

jhogendorn
  • 5,931
  • 3
  • 26
  • 35

1 Answers1

6

The answer is yes. You need to specify your constraint against the object rather than a parameter, and specify the constraint that its a class level constraint. A somewhat verbose example is this:

config.yml

validator.my.uniquename:
  class: FQCN\To\My\ConstraintValidator
  arguments: [@service_container]
  tags:
    - { name: validator.constraint_validator, alias: ConstraintValidator }

validation.yml

FQCN\To\My\Entity:
  constraints:
    - FQCN\To\MyConstraint: ~

(no args for the constraint in this example)

My Constraint

namespace FQCN\To;

use 
  Symfony\Component\Validator\Constraint
  ;

/**
 * @Annotation
 */
class MyConstraint extends Constraint
{
  public $message = 'Constraint not valid';

  public function validatedBy()
  {
    return 'ConstraintValidator';
  }

  public function getTargets() 
  {
    # This is the important bit.
    return self::CLASS_CONSTRAINT;
  }
}

My ConstraintValidator

class MyConstraintValidator extends ConstraintValidator
{
  protected $container;

  function __construct($container)
  {
    $this -> container = $container;
  }

  function isValid($object, Constraint $constraint)
  {
    # validation here.
    return true;
  }
}
Hannes
  • 8,147
  • 4
  • 33
  • 51
jhogendorn
  • 5,931
  • 3
  • 26
  • 35
  • Any tips to solve `The constraint MyBundle\Validator\Constraint cannot be put on properties or getters` ? – greg May 06 '13 at 19:55
  • @greg and for future visitors, you must put the constraint annotation ABOVE the class declaration. – keyboardSmasher Feb 13 '14 at 15:15
  • More precision when writing answers please. – webrama.pl Mar 16 '14 at 17:39
  • @PAM, how would you advise for more precision? The example seems quite precise to me. – jhogendorn Mar 18 '14 at 00:58
  • Ok, maybe I didn't understand something. Finally I figured it out with official docs. I can't give you +1 back until you edit the post :) – webrama.pl Mar 18 '14 at 07:24
  • The key is in Constraint::getTargets() method: by default it uses self::PROPERTY_CONSTRAINT but to validate the entire entity it is necessary to use self::CLASS_CONSTRAINT constant. Everything else is standard validator. – Denys Horobchenko Mar 20 '18 at 10:02