Редактирование формы Zend и проверка базы данных Zend Не существует записей


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

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

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

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

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

При проверке формы этот валидатор проверит, что содержимое элемента данных еще не существует в таблице. Таким образом, вставка в тест может продолжаться без нарушения УНИКАЛЬНОГО квалификатора полей данных.

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

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

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

В Документах по проверке Zend говорится о добавлении параметра в средство проверки NoRecordExists() с целью исключения записи из процесса проверки. Идея состоит в том, чтобы "проверить таблицу на наличие любых совпадающих строк, но игнорировать любые совпадения, в которых поле a имеет это конкретное значение". Такой вариант использования необходим для проверки элемента при редактировании таблицы. Псевдокод для этого в 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 указывает, где Я бы хотел, чтобы произошла привязка значения $ к валидатору 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 для проверки уникальности и исключить строку с идентификатором такого-то. Конечно, это заставило меня задуматься о том, как я буду привязывать форму к слою БД, который модель должна скрывать!

Author: Peter M, 2010-02-02

7 answers

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

  1. В свою ФОРМУ вы добавляете этот валидатор (например, поле электронной почты):

 

$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()))
                {

    ....

Вот и все!

 6
Author: pdolinaj, 2012-08-18 10:35:42

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

$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'
                    )
                )
            )
        )
    ));
 4
Author: Gaurav Sharma, 2012-08-21 10:10:53

Просмотрев подавляющий ответ, я решил, что буду использовать пользовательский валидатор

 1
Author: Peter M, 2010-02-09 13:52:26
 1
Author: MiPnamic, 2017-05-23 10:29:38
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));
 1
Author: Rizky Zulkarnaen, 2012-11-22 22:10:37

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

 0
Author: Thom Wiggers, 2010-02-02 14:42:21

Я только что попробовал этот пример для 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())) {

Надеюсь, это поможет вам, люди!

Спасибо

 0
Author: Aditya P Bhatt, 2012-08-16 08:23:19