2011-02-24 32 views
6

我在两个单独的上下文中使用表单类:既创建一个新记录,也编辑该记录。我已经设置了后验证器,如下所示,以检查URL字段是否唯一。更新/编辑上下文中的sfValidatorDoctrineUnique

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

当我创建一条新记录时,验证器很有效。但是,在编辑现有记录时,由于它将自己检测为重复,所以会引发错误。换句话说,如果我编辑记录但不更改URL,则会引发重复错误。

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

+0

汤姆,请让我知道你找到了解决办法,因为我有相同问题。谢谢。 – tipu 2011-04-18 20:59:43

+1

我的解决方案发现:sfValidatorDoctrineUnique的第一个参数应该有一个键“primary_key”,值应​​该是表的主键。那么您需要确保您的表单中的名称与主键匹配。所以如果你正在编辑一个模型页面,其ID为3,你需要。最后我还将primary_key列放在我的表单中,所以$ this-> setValidator('id',new sfValidatorString(array('required'=> true)))。总而言之,3个文件的变化完成了工作。 – tipu 2011-04-18 21:56:17

回答

6

更新情况确实由sfValidatorDoctrineUnique处理。

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

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

默认情况下,主键是内省的。你可以为它提供* primary_key *选项传递给验证器。

+0

谢谢,听起来像我正在寻找。你能提供一个如何使用它的简单例子吗?似乎没有很好的记录。 – Tom 2011-02-24 22:31:51

+0

....不用担心,想通了。最初想到我需要调用这种方法。谢谢你的帮助。 – Tom 2011-02-24 23:17:30

+1

hi kuba, 你能解释一下如何使用sfValidatorDoctrineUnique :: isUpdate()或sfValidatorDoctrineUnique与primary_key选项的例子 – 2011-07-12 12:50:18

4

在其他的答案指出,一定要确保以下是很重要的:

  • 的更新对象的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());