Я медленно наращиваю свои навыки Zend, создавая некоторые служебные веб-сайты для собственного использования. Я использую Zend Forms и Form validation, и до сих пор был счастлив, что я понимаю способ Zend делать вещи. Однако я немного смущен тем, как использовать Zend_Validate_Db_NoRecordExists() в контексте формы редактирования и поле, которое сопоставляется столбцу базы данных, которое должно быть уникальным.
Например, используя эту простую таблицу
TABLE Test
(
ID INT AUTO_INCREMENT,
Data INT UNIQUE
);
Если бы я просто добавлял новую строку в Test Table, я мог бы добавить валидатор в элемент формы Zend для поля Data как такового:
$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data') )
При проверке формы этот валидатор проверит, что содержимое элемента данных еще не существует в таблице. Таким образом, вставка в Test может идти вперед, не нарушая квалификацию Data data UNIQUE.
Однако при редактировании существующей строки таблицы Test ситуация отличается. В этом случае валидатор должен проверить, соответствует ли значение элемента одному из двух условий взаимоисключающих условий:
-
Пользователь изменил значение элемента, а новое значение в настоящее время существуют в таблице.
-
Пользователь Не изменил значение элемента. Таким образом, значение делает в настоящее время в таблице (и это нормально).
Dend 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, когда форма была сначала заполнена данными - IE - значение Data, первоначально прочитанное из строки Test table. Но в типичных шаблонах Zend форма создается и заполняется двумя отдельными шагами, что исключает привязку значения exclude к требуемому значению элемента.
Следующие кодовые обозначения 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. Моя форма имеет идентификатор записи как скрытое поле, так что, учитывая имена таблиц и столбцов, я мог бы обработать некоторый SQL для проверки на уникальность и исключить строку с идентификатором такого типа. Конечно, это заставило меня задуматься о том, как я привяжу форму к слою дБ, который должна скрыть модель.