Zend 表单编辑和 Zend_Validate_Db_NoRecordExists
我正在通过构建一些供自己使用的实用程序网站来慢慢增强我的 Zend 技能。我一直在使用 Zend Forms 和表单验证,到目前为止,我很高兴我已经了解了 Zend 的做事方式。然而,我对如何在编辑表单和映射到必须唯一的数据库列的字段的上下文中使用 Zend_Validate_Db_NoRecordExists() 有点困惑。
例如,使用这个简单的表
TABLE Test
(
ID INT AUTO_INCREMENT,
Data INT UNIQUE
);
如果我只是向表测试添加一个新行,我可以向数据字段的 Zend Form 元素添加一个验证器,如下所示:
$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data') )
在表单验证时,此验证器将检查数据元素的内容表中尚不存在。因此,可以继续插入 Test,而不会违反数据字段 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)绑定到实例化时的验证器(也是实例化表单时)。但是,当表单编辑记录时,当表单最初填充数据时,该值需要绑定到 $data 字段的内容 - 即最初从测试表行读取的数据值。但在典型的 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 层!
I am slowly building up my Zend skills by building some utility websites for my own use. I have been using Zend Forms and Form validation and so far have been happy that I have been understanding the Zend way of doing things. However I am a bit confused with how to use Zend_Validate_Db_NoRecordExists() in the context of an edit form and a field that maps to database column that has to be unique.
For example using this simple table
TABLE Test
(
ID INT AUTO_INCREMENT,
Data INT UNIQUE
);
If I was simply adding a new row to the Table Test, I could add a validator to the Zend Form element for the Data field as such:
$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data') )
At form validation this validator will check that the contents of the Data element does not already exist in the table. Thus the insert into Test can go ahead without violating the Data fields UNIQUE qualifier.
However the situation is different when editing an existing row of the Test table. In that case the validator needs to check that the element value meets one of two mutually exclusive conditions conditions:
The user has changed the element value, and the new value does not currently
exist in the table.The user has Not changed the element value. Thus the value does currently exist in the table (and this is OK).
The Zend Validation Docs talk about adding a parameter to the NoRecordExists() validator for the purpose of excluding records from the validation process. The idea being to "validate the table looking for any matching rows, but ignore any hits where the a field has this specific value". Such a use case is what is needed for the validating the element when editing a table. The pseudo code to do this in 1.9 is like so (actually I got this from the 1.9 source code - I think the current docs may be wrong):
$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data',
array ('field'=>'Data', 'Value'=> $Value) );
The problem is that the value that is to be excluded ($Value) is bound to the validator at the time it is instantiated (also when the form is instantiated). But when the form is editing a record, that value needs to be bound to the contents of the $data field when the form was initially populated with data - IE the Data value initially read from the Test table row. But in typical Zend patterns a form is instantiated and populated in two separate steps which precludes binding the exclude value to the desired element value.
The following Zend psuedo code marks where I would like the binding of $Value to the NoRecordExists() validator to occur (and note that this is a common Zend controller pattern):
$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
}
I could sub-class Zend_Form and override the populate() method to do a one-shot insertion of the NoRecordExists() validator on initial form population, but that seems like a huge hack to me. So I wanted to know what other people think and is there some pattern already written down that solves this problem?
Edit 2009-02-04
I've been thinking that the only decent solution to this problem is to write a custom validator and forget about the Zend version. My form has the record ID as hidden field, so that given the table and column names I could craft some SQL to test for uniqueness and exclude the row with an ID of such an such. Of course this started me thinking about how I would be tying the form to the dB layer that the Model is supposed to hide!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
它是这样完成的:
就是这样!
This is how it's done:
That's it!
这也将起作用:
This will also work :
在查看了压倒性的回应后,我决定使用自定义验证器
After reviewing the overwhelming response I've decided that I'm going with a custom validator
看看这个:
我提出并由 Dickie 很好解决的答案
Look at this one:
Answer raised by me and well-solved by Dickie
现在你可以使用:
Now u can use:
您可以只调用
$form->getElement('input')->removeValidator('Zend_Validator_Db_NoRecordExists');
而不是提供排除。You could just call
$form->getElement('input')->removeValidator('Zend_Validator_Db_NoRecordExists');
instead of supplying the exclusion.我刚刚尝试过此示例以确保
电子邮件地址
唯一性,它与以下内容完美配合:1]在我的表单中:
这是我需要为
添加的特殊内容唯一的电子邮件地址
工作:2]在我的控制器中:
希望它可以帮助你们!
谢谢
I have just tried this example for
email address
uniqueness and it works perfectly with below stuffs :1] In my form:
Here's something special that I needed to add for
unique email address
to work:2] In my controller:
Hope it helps you people !
Thanks