7

我在两个不同的上下文中使用表单类:既可以创建新记录,也可以编辑该记录。我设置了如下验证器来检查 URL 字段是否唯一。

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

当我创建新记录时,验证器工作得很好。但是,在编辑现有记录时,它会引发错误,因为它将自己检测为重复。换句话说,如果我编辑记录但不更改 URL,则会引发重复错误。

这一定是一个常见问题,所以我想知道 Symfony 的处理方式是什么?基本上我希望它在保存时忽略自己(不存在重复),但仍然运行后验证器以确保不存在真正的重复。

4

2 回答 2

6

更新情况确实由 sfValidatorDoctrineUnique 处理。

在您的情况下,如果具有给定 URL 的对象已经存在,验证器将检查您是否正在执行更新操作。使用sfValidatorDoctrineUnique::isUpdate()方法进行检查。

您的主键需要在提交的值中。

默认情况下,主键是自省的。您可以通过传递给验证器的 *primary_key* 选项来提供它。

于 2011-02-24T22:10:38.650 回答
5

如其他答案所述,确保以下几点很重要:

  • 更新对象的 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());
    
于 2011-12-30T17:13:52.613 回答