title: SYMFONY custom CONSTRAINT -> Pass variable to a custom CONSTRAINT / How CONSTRAINT binded to a form field can OVERRIDE CONSTRAINT in ANNOTATION
body: <p>My goal: I built a custom constraint in SYMFONY, I needed to pass a variable to that constraint. </p>
  
  <p>The context: The constraint do a check if a value is unique in the DB, if it is not, it raises a CONSTRAINT alert. That works alright when the FORM is used to create a new tuple in the DB <strong>but if it is an edit it raises an exception which should be bypass by checking that the value already existing, exists for the tuple Id being edited</strong>.</p>
  
  <p>Hence I needed to pass the Id of the tuple being edited to my constraint check.</p>
  
  <p>At first I implemented my custom constraint in my entity:</p>
  
  <pre><code>class MyEntity{
  
      /**
      * @MyBundleAssert\CheckValueAlreadyInDB(
      *     message = "already_exists_in_db",
      *     fieldToSearch = "my_value",
      *     tableToSearch = "my_table"
      *)
      */
      private myValue;
  
  } 
  </code></pre>
  
  <p>As one can see, I did not find a way to implement a way to pass a VARIABLE using the constraint with ANNOTATION. By searching, I understood I could do that by using the <code>__construct()</code> of my custom constraint class:  </p>
  
  <pre><code>/**
   * @Annotation
   */
  class CheckValueAlreadyInDB extends Constraint{
  public $message;
  public $fieldToSearch;
  public $tableToSearch;
  public $idToCheck;
  public $idToCheckFieldName;
  
  public function __construct($options){
      if(count($options)&gt;0){
          $this-&gt;idToCheck = $options['idToCheck'];
          $this-&gt;idToCheckFieldName = $options['idToCheckFieldName'];
          $this-&gt;fieldToSearch = $options['fieldToSearch'];
          $this-&gt;tableToSearch = $options['tableToSearch'];
          $this-&gt;message = $options['message'];
      }
  }
  
  public function validatedBy()
  {
      return 'validator_check_value_already_in_db';
  }
  }
  </code></pre>
  
  <p>And, the ConstraintValidator extended class linked to it:</p>
  
  <pre><code>class CheckValueAlreadyInDBValidator extends ConstraintValidator
  {
      private $con;
  
      public function __construct($con){
          $this-&gt;con = $con;
      }
  
      public function validate($value, Constraint $constraint)
      {
          ////My stuff to get a record from the DB////
          $sel = new PdoSelect($this-&gt;con);
          $search = $sel-&gt;returnRecordsInTableForSpecificKey([$constraint-&gt;fieldToSearch],[$value],  $constraint-&gt;tableToSearch,false);
         //////////////////////////////////////////////
  
          $sameId = false;
          if($constraint-&gt;idToCheck!==null){
              $idToCheckInRetrieveRecord = $search-&gt;{$constraint-&gt;idToCheckFieldName};            
              $sameId = ($idToCheckInRetrieveRecord==$constraint-&gt;idToCheck)?true:false;
          }
  
          if($search!=null&amp;&amp;!$sameId){
              $this-&gt;context-&gt;buildViolation($constraint-&gt;message)
                  -&gt;setParameter('%string%', $value)
                  -&gt;addViolation();
          }
      }
  }
  </code></pre>
  
  <p>With service:</p>
  
  <pre><code>validator.unique.check_value_already_in_db:
      class: MyBundle\Form\CustomConstraints\CheckValueAlreadyInDBValidator
      arguments: ['@doctrine.dbal.default_connection']
      tags:
          - { name: validator.constraint_validator, alias: validator_check_value_already_in_db }
  </code></pre>
  
  <p>I my FORM (AbstractType extended class) for the field regarding myValue, I did edit the <code>constraints</code> attribute.</p>
  
  <pre><code>class MyEntityType extends AbstractType {     
  public function buildForm(FormBuilderInterface $builder, array $options)
        {
  
      ....
          $builder-&gt;add('myValue',****Type::class,array(
            'constraints' =&gt; array(
                new CheckValueAlreadyInDB(array(
                  'idToCheck'=&gt;$options['data']-&gt;getId(),
                  'idToCheckFieldName'=&gt;'id',
                  'fieldToSearch'=&gt;'my_value',
                  'tableToSearch'=&gt;'my_table',
                  'message' =&gt; "value_already_exists_in_db"))
              )
            ));
  
      ...
      }
  }
  </code></pre>
  
  <p>I thought that the CONSTRAINT defined in the <code>buildForm()</code> would override the one defined in the     <code>* @MyBundleAssert\CheckValueAlreadyInDB(..)</code> of MyEntity class (which should be the default behaviour). But It did not! <strong>I had to delete the ANNOTATION above MyEntity to make the constraint work as defined in the <code>buildForm()</code>.</strong></p>
  
  <p>Does anyone know if there is a setting that could permit to have a constraint in a <code>buildForm()</code> overriding one existing as an ANNOTATION in MyEntity, but still let the ANNOTATION above a field in MyEntity be the default behavior? Or is there is a way to pass VARIABLE to ANNOTATIONS?</p>