2010-02-01 5 views
10

Я медленно наращиваю свои навыки Zend, создавая некоторые служебные веб-сайты для собственного использования. Я использую Zend Forms и Form validation, и до сих пор был счастлив, что я понимаю способ Zend делать вещи. Однако я немного смущен тем, как использовать Zend_Validate_Db_NoRecordExists() в контексте формы редактирования и поле, которое сопоставляется с столбцом базы данных, который должен быть уникальным.Zend Form Edit и Zend_Validate_Db_NoRecordExists

Например, используя эту простую таблицу

TABLE Test 
(
    ID INT AUTO_INCREMENT, 
    Data INT UNIQUE 
); 

Если бы я просто добавить новую строку в таблице Test, я мог бы добавить валидатор к элементу Зенд формы для поля данных, как, например:

$data = new Zend_Form_Element_Text('Data'); 
$data->addValidator(new Zend_Validate_Db_NoRecordExists('Test', 'Data')) 

При проверке формы этот валидатор проверяет, что содержимое элемента данных еще не существует в таблице. Таким образом, вставка в Test может идти вперед, не нарушая поля Data data UNIQUE.

Однако при редактировании существующей строки тестовой таблицы ситуация отличается. В этом случае валидатор должен проверить, что значение элемента соответствует один из двух взаимоисключающих условий условий:

  1. Пользователь изменил значение элемента, и новое значение в настоящее время не существует в таблице.

  2. Пользователь имеет Не изменил значение элемента. Таким образом, значение делает в настоящее время в таблице (и это нормально).

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, когда форма была сначала заполнена данными - IE - значение Data, первоначально прочитанное из строки Test table. Но в типичных шаблонах Zend форма создается и заполняется двумя отдельными шагами, что исключает привязку значения exclude к требуемому значению элемента.

Следующие Zend псевдо кодовых обозначений, где я хотел бы связыванию $ 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 
} 

Я мог суб -class Zend_Form и переопределить метод populate(), чтобы сделать одноразовую вставку валидатора NoRecordExists() для начальной группы, но это кажется огромным взломом для меня. Поэтому я хотел знать, что думают другие люди, и есть ли какая-то модель, уже записанная, которая решает эту проблему?

Редактировать 2009-02-04

Я думал, что единственное порядочное решение этой проблемы заключается в написании пользовательского валидатора и забыть о версии Zend. Моя форма имеет идентификатор записи как скрытое поле, так что, учитывая имена таблиц и столбцов, я мог бы обработать некоторый SQL для проверки на уникальность и исключить строку с идентификатором такого типа. Конечно, это заставило меня задуматься о том, как я привяжу форму к слою дБ, который должна скрывать модель.

ответ

1

После рассмотрения подавляющего ответа я решил, что я буду с валидатора

0

Вы можете просто позвонить $form->getElement('input')->removeValidator('Zend_Validator_Db_NoRecordExists'); вместо предоставления исключения.

+0

@The Guy - Это, казалось бы поражение цели обеспечения того, чтобы данные уникальны до делать обновление дБ во время цикла редактирования. Я чувствую, что это также приводит к загрязнению контроллера чем-то, что принадлежит форме. –

+0

Да, я согласен, что это немного хаки. На самом деле я не очень доволен тем, как Zend_Form работает прямо сейчас. Хотя я все еще использую старую реализацию стиля ZF 1.6: P –

+0

Guy - Я только начал с 1,9 в декабре, поэтому я все еще изучаю вещи, но такие вещи заставляют меня идти «хмммм»? –

6

Вот как это делается:

  1. Я ваш FORM, добавь этот валидатор (например, по электронной почте поле):

 

$email->addValidator('Db_NoRecordExists', true, array('table' => 'user', 'field' => 'email')); 
  1. Не добавлять пользовательское сообщение об ошибке для этого, так как после того, что он не работает для меня, например:

 

$email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.'); 

 

  1. В вашем контроллере добавить это:

 

/* Don't check for Db_NoRecordExists if editing the same field */ 

    $form->getElement('email') 
      ->addValidator('Db_NoRecordExists', 
           false, 
           array('table' => 'user', 
             '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())) 
       { 

    .... 

Это все!

1
private $_id; 

public function setId($id=null) 
{ 
    $this->_id=$id;  
} 

public function init() 
{ 
    ..... 
    if(isset($this->_id)){ 
     $email->addValidator('Db_NoRecordExists', false, array('table' => 'user', 'field' => 'email','exclude' => array ('field' => 'id', 'value' => $this->_id))); 
     $email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');  
    } 

Теперь вы можете использовать:

$form = new Form_Test(array('id'=>$id)); 
0

Я только попробовал этот пример email address уникальность и она прекрасно работает с ниже питания:

1] В моей форме:

// Add an email element 
    $this->addElement('text', 'email', array(
     'label'  => 'Email :', 
     'required' => true, 
     'filters' => array('StringTrim'), 
     'validators' => array(
      'EmailAddress', 
     ) 
    )); 

Вот что-то особенное, что мне нужно добавить для unique email address работы:

$email = new Zend_Form_Element_Text('email'); 
    $email->addValidator('Db_NoRecordExists', true, array('table' => 'guestbook', 'field' => 'email')); 

2] В моем контроллере:

$form->getElement('email') 
    ->addValidator('Db_NoRecordExists', 
         false, 
         array('table' => 'guestbook', 
           'field' => 'email', 
           'exclude' => array ('field' => 'id', 'value' => $request->get('id')))); 

if ($this->getRequest()->isPost()) { 
     if ($form->isValid($request->getPost())) { 

Надеется, что это помогает вам человек!

Благодаря

4

Это также будет работать:

$this->addElement('text', 'email', array(
     'label'  => 'Your email address:', 
     'required' => true, 
     'filters' => array('StringTrim'), 
     'validators' => array(
      'EmailAddress', 
      array('Db_NoRecordExists', true, array(
        'table' => 'guestbook', 
        'field' => 'email', 
        'messages' => array(
         'recordFound' => 'Email already taken' 
        ) 
       ) 
      ) 
     ) 
    ));