例如使用这个简单的表
TABLE Test ( ID INT AUTO_INCREMENT,Data INT UNIQUE );
如果我只是在Table Test中添加一个新行,我可以在Data字段的Zend Form元素中添加一个验证器:
$data = new Zend_Form_Element_Text('Data'); $data->addValidator( new Zend_Validate_Db_NoRecordExists('Test','Data') )
在表单验证时,该验证器将检查表中Data元素的内容是否不存在.因此,插入测试可以在不违反Data字段UNIQUE限定符的情况下进行.
但是,当编辑测试表的现有行时,情况会有所不同.在这种情况下,验证器需要检查元素值是否满足两个互斥条件之一条件:
>用户已更改元素值,并且新值当前不存在
存在于表中.
>用户没有更改元素值.因此,该值当前存在于表中(这可以).
Zend Validation Docs讨论将参数添加到NoRecordExists()验证器中,以便从验证过程中排除记录.这个想法是“验证表查找任何匹配的行,但忽略某个字段具有此特定值的任何命中”.这样的用例是编辑表时验证元素所需要的.在1.9中这样做的伪代码就像这样(实际上我从1.9源代码中得到这个 – 我认为当前文档可能是错误的):
$data = new Zend_Form_Element_Text('Data'); $data->addValidator( new Zend_Validate_Db_NoRecordExists('Test','Data',array ('field'=>'Data','Value'=> $Value) );
问题是要被排除的值($Value)在实例化时被绑定到验证器(也是在实例化表单时).但是当表单正在编辑记录时,当表单最初填充数据时,该值需要绑定到$数据字段的内容 – IE最初从测试表行读取数据.但是在典型的Zend模式中,一个表单被实例化和填充在两个单独的步骤中,排除了将排除值绑定到所需的元素值.
以下Zend psuedo代码标记我想要将$Value绑定到NoRecordExists()验证器发生(注意这是一个常见的Zend控制器模式):
$form = new Form() if (is Post) { $formData = GetPostData() if ($form->isValid($formData)) { Update Table with $formData Redirect out of here } else { $form->populate($formData) } } else { $RowData = Get Data from Table $form->populate($RowData) <=== This is where I want ('value' => $Value) bound }
我可以使用Zend_Form子类,并覆盖populate()方法,以便在初始窗体上单次插入NoRecordExists()验证器,但这对我来说似乎是一个巨大的错误.所以我想知道其他人的想法,还有一些已经写下来的模式解决了这个问题?
编辑2009-02-04
我一直在想,这个问题的唯一体面的解决方案是编写自定义验证器,并忘记Zend版本.我的表单具有记录ID作为隐藏字段,因此给定表和列名称,我可以制作一些sql来测试唯一性,并排除具有这样的ID的行.当然,这让我想起了如何将形式绑定到模型应该隐藏的dB层.
>我的FORM,你添加这个验证器(例如email字段):
$email->addValidator('Db_NoRecordExists',true,array('table' => 'user','field' => 'email'));
$email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');
在你的控制器中添加:
/* Don't check for Db_NoRecordExists if editing the same field */ $form->getElement('email') ->addValidator('Db_NoRecordExists',false,'field' => 'email','exclude' => array ('field' => 'id','value' => $this->request->get('id')))); And after this you do verifications,e.g.: if ($this->getRequest()->isPost()) { if($form->isValid($this->getRequest()->getPost())) { ....
而已!