2016-05-27 6 views
0

Mein Ziel: Ich baute eine benutzerdefinierte Einschränkung in SYMFONY, ich musste eine Variable an diese Einschränkung übergeben.SYMFONY benutzerdefinierte CONSTRAINT -> Variable an einen benutzerdefinierten CONSTRAINT übergeben/Wie CONSTRAINT an ein Formularfeld gebunden kann CONSTRAINT in ANNOTATION ÜBERNEHMEN

Der Kontext: Die Einschränkung überprüft, ob ein Wert in der DB eindeutig ist. Ist dies nicht der Fall, wird eine CONSTRAINT-Warnung ausgelöst. Das funktioniert gut, wenn die FORM verwendet wird, um ein neues Tupel in der DB zu erstellen, aber wenn es eine Bearbeitung ist, löst es eine Ausnahme aus, die umgangen werden soll, indem der bereits vorhandene Wert für die Tupel-ID bearbeitet wird.

Daher musste ich die ID des Tupels, das bearbeitet wurde, an meine Constraint-Prüfung übergeben.

Zuerst implementiert ich meine benutzerdefinierte Einschränkung in meiner Einheit:

class MyEntity{ 

    /** 
    * @MyBundleAssert\CheckValueAlreadyInDB(
    *  message = "already_exists_in_db", 
    *  fieldToSearch = "my_value", 
    *  tableToSearch = "my_table" 
    *) 
    */ 
    private myValue; 

} 

Wie man sehen kann, kann ich nicht einen Weg, einen Weg zu implementieren passieren eine Variable mit der Einschränkung mit ANNOTATION gefunden hat. Durch die Suche, verstand ich, was ich tun konnte, dass durch die __construct() meine benutzerdefinierte Constraint-Klasse:

/** 
* @Annotation 
*/ 
class CheckValueAlreadyInDB extends Constraint{ 
public $message; 
public $fieldToSearch; 
public $tableToSearch; 
public $idToCheck; 
public $idToCheckFieldName; 

public function __construct($options){ 
    if(count($options)>0){ 
     $this->idToCheck = $options['idToCheck']; 
     $this->idToCheckFieldName = $options['idToCheckFieldName']; 
     $this->fieldToSearch = $options['fieldToSearch']; 
     $this->tableToSearch = $options['tableToSearch']; 
     $this->message = $options['message']; 
    } 
} 

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

Und der ConstraintValidator erweiterte Klasse mit ihm verbunden:

class CheckValueAlreadyInDBValidator extends ConstraintValidator 
{ 
    private $con; 

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

    public function validate($value, Constraint $constraint) 
    { 
     ////My stuff to get a record from the DB//// 
     $sel = new PdoSelect($this->con); 
     $search = $sel->returnRecordsInTableForSpecificKey([$constraint->fieldToSearch],[$value], $constraint->tableToSearch,false); 
     ////////////////////////////////////////////// 

     $sameId = false; 
     if($constraint->idToCheck!==null){ 
      $idToCheckInRetrieveRecord = $search->{$constraint->idToCheckFieldName};    
      $sameId = ($idToCheckInRetrieveRecord==$constraint->idToCheck)?true:false; 
     } 

     if($search!=null&&!$sameId){ 
      $this->context->buildViolation($constraint->message) 
       ->setParameter('%string%', $value) 
       ->addViolation(); 
     } 
    } 
} 

Mit Service:

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 } 

Ich meine FORM (AbstractType erweiterte Klasse) für das Feld in Bezug auf myValue, habe ich das constraints Attribut bearbeiten.

class MyEntityType extends AbstractType {  
public function buildForm(FormBuilderInterface $builder, array $options) 
     { 

    .... 
     $builder->add('myValue',****Type::class,array(
      'constraints' => array(
       new CheckValueAlreadyInDB(array(
       'idToCheck'=>$options['data']->getId(), 
       'idToCheckFieldName'=>'id', 
       'fieldToSearch'=>'my_value', 
       'tableToSearch'=>'my_table', 
       'message' => "value_already_exists_in_db")) 
      ) 
     )); 

    ... 
    } 
} 

Ich dachte, dass die Einschränkung in der buildForm() definiert die man in der * @MyBundleAssert\CheckValueAlreadyInDB(..) von MyEntity Klasse definiert würde außer Kraft setzen (die das Standardverhalten sein sollte). Aber es hat nicht! Ich musste die ANNOTATION über MyEntity löschen, damit die Einschränkung wie in buildForm() definiert funktioniert.

Weiß jemand, ob es eine Einstellung, die eine Einschränkung in einem buildForm() zwingenden einem bestehenden als ANNOTATION in MyEntity haben erlauben könnte, aber immer noch die ANNOTATION über ein Feld in MyEntity läßt das Standardverhalten sein? Oder gibt es eine Möglichkeit, VARIABLE an ANNOTATIONEN zu übergeben?

Antwort

0

Ich fand die Lösung.

Mein Fehler war zu versuchen, Einschränkungen in der Klasse MyEntityType verwenden erweitert Abstract:

$builder->add('myValue',****Type::class,array(
    'constraints' => array(
     new CheckValueAlreadyInDB(array(
     'idToCheck'=>$options['data']->getId(), 
     'idToCheckFieldName'=>'id', 
     'fieldToSearch'=>'my_value', 
     'tableToSearch'=>'my_table', 
     'message' => "value_already_exists_in_db")) 
    ) 
)); 

ES NICHT NUTZEN SIE HIER

Werfen Sie einen Blick auf class-constraint-validator Abschnitt im doc.

Implementieren Sie die erweiterte Klasse ConstraintValidator über der Klasse der Entität, wo der Validator seine Prüfung ausführen muss und nicht über einem Attribut der Entity-Klasse. Auf diese Weise kann man auf andere Attribute der Entität zugreifen und sie als Bedingung in der erweiterten Klasse ConstraintValidator verwenden.