2016-05-27 3 views
0

Моя цель: я создал собственное ограничение в SYMFONY, мне нужно было передать переменную этому ограничению.SYMFONY custom CONSTRAINT -> Передать переменную в пользовательский CONSTRAINT/Как CONSTRAINT, привязанный к полю формы, может OVERRIDE CONSTRAINT в ANNOTATION

Контекст: Ограничение проверяет, уникально ли значение в БД, если это не так, оно вызывает предупреждение CONSTRAINT. Это работает хорошо, когда FORM используется для создания нового кортежа в БД , но если он является редактированием, он вызывает исключение, которое должно быть обходным путем проверки того, что уже существующее значение существует для того, чтобы отредактированный кортеж Id.

Следовательно, мне нужно было передать Идентификатор кортежа, который будет отредактирован, в мою проверку ограничений.

Сначала я реализовал свое собственное ограничение в моей сущности:

class MyEntity{ 

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

} 

Как можно видеть, я не нашел способ реализовать способ передать переменный, используя ограничение с аннотацией. При поиске, я понял, я мог бы сделать это с помощью __construct() моего пользовательского класса ограничения:

/** 
* @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'; 
} 
} 

И, тем ConstraintValidator расширен класс связанных с ним:

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(); 
     } 
    } 
} 

С обслуживанием:

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 } 

I my FORM (расширенный класс AbstractType) для поля, относящегося к myValue, я редактировал атрибут constraints.

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")) 
      ) 
     )); 

    ... 
    } 
} 

Я думал, что ограничение, определенное в buildForm() бы переопределить один, определенный в * @MyBundleAssert\CheckValueAlreadyInDB(..) класса MyEntity (который должен быть по умолчанию). Но это не так! Мне пришлось удалить ANNOTATION над MyEntity, чтобы сделать работу ограничения, как определено в buildForm().

Кто-нибудь знает, если есть параметр, который может позволить иметь ограничение в buildForm() переопределяя один существующий как аннотации в MyEntity, но все-таки пусть АННОТАЦИЯ над полем в MyEntity быть по умолчанию? Или есть способ передать ПЕРЕМЕННЫЕ АННОТАЦИИ?

ответ

0

Я нашел решение.

Моя ошибка заключалась в попытке использовать ограничения в классе MyEntityType расширяет AbstractType:

$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")) 
    ) 
)); 

НЕ ИСПОЛЬЗОВАТЬ ЕГО ЗДЕСЬ

Посмотрите class-constraint-validator раздел в док.

Внедрение расширенного класса ConstraintValidator над классом объекта, где валидатор должен выполнить проверку и не над одним атрибутом класса Entity. Таким образом, вы можете получить доступ к другим атрибутам объекта и использовать его в качестве условных выражений в расширенном классе ConstraintValidator.

Смежные вопросы