sfValidatorDoctrineUnique в контексте обновления / редактирования - PullRequest
7 голосов
/ 25 февраля 2011

Я использую класс формы в двух разных контекстах: как для создания новой записи, так и для редактирования этой записи.Я установил пост-валидатор следующим образом, чтобы проверить уникальность поля URL.

$this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
   new sfValidatorDoctrineUnique(array('model' => 'Page', 'column' => array('url')), array('invalid' => 'This URL already exists.'))
)));

Валидатор отлично работает, когда я создаю новую запись.Однако при редактировании существующей записи он выдает ошибку, поскольку обнаруживает себя как дубликат.Другими словами, если я редактирую запись, но не изменяю URL, она выдает повторяющуюся ошибку.

Это должно быть распространенной проблемой, поэтому мне интересно, каким образом Symfony справится с этим?По сути, я бы хотел, чтобы при сохранении он игнорировался (дубликатов не было), но все равно запускал пост-валидатор, чтобы убедиться, что нет настоящих дубликатов.

Ответы [ 2 ]

6 голосов
/ 25 февраля 2011

Ситуация обновления действительно обрабатывается sfValidatorDoctrineUnique.

В вашем случае, если объект с данным URL уже существует, валидатор проверит, выполняете ли вы операцию обновления.Проверка выполняется с помощью метода sfValidatorDoctrineUnique :: isUpdate () .

Ваш первичный ключ (и) должен быть в предоставленных значениях.

По умолчанию первичный ключ является самоанализом.Вы можете предоставить его с параметром * primary_key *, переданным валидатору.

5 голосов
/ 30 декабря 2011

Как отмечено в других ответах, важно убедиться в следующем:

  • Значение PK для обновленного объекта должно присутствовать в представленных значениях формы.
  • Валидатор sfValidatorDoctrineUnique должен знать все значения, отправленные с формой.

Для этого необходимо выполнить следующие шаги:

  1. Добавьте скрытый ввод, который содержит (обычно) значение PK для вашего объекта:

    class MyModelForm extends BaseMyModelForm
    {
      public function configure(  )
      {
        if( ! $this->isNew() )
        {
          $this->widgetSchema['id']    = new sfWidgetFormInputHidden();
          $this->validatorSchema['id'] = new sfValidatorNumber(array(
              'required' => true
            , 'min'      => 1
          ));
        }
    
        ...
      }
    
      ...
    }
    
    • Обратите внимание, что этот дополнительный ввод необходимо добавлять только при обновлении.
  2. Переместите sfValidatorDoctrineUnique в фазу после проверки:

    class MyModelForm extends BaseMyModelForm
    {
      public function configure(  )
      {
        $this->widgetSchema['unique_column']    = new sfWidgetFormInputText();
        $this->validatorSchema['unique_column'] = new sfValidatorPass();
    
        ...
    
        $this->mergePostValidator(new sfValidatorDoctrineUnique(array(
            'required' => true
          , 'model'    => 'MyModel'
          , 'column'   => 'unique_column'
        )));
      }
    
      ...
    }
    
    • Вам нужно будет использовать $this->mergePostValidator(), чтобы добавить валидатор к этапу после проверки, чтобы все представленные значения были предоставлены валидатору.

    • Обратите внимание, что вам все равно нужно предоставить валидатор для виджета с уникальным столбцом, иначе вы получите сообщение об ошибке «Неожиданное поле дополнительной формы» при отправке формы.

  3. Убедитесь, что вы передаете обновляемый объект конструктору вашей формы:

    $this->form = new MyModelForm($this->getRoute()->getObject());
    
...