
Tworząc formularze przy użyciu Zend_From możemy szybko dojść do sytuacji gdzie standardowy zestaw walidatorów nie spełni naszych potrzeb. Najlepszy przykład to formularz rejestracji i sprawdzanie czy pola "hasło" oraz "powtórz hasło" zawierają identyczne wartości. Albo formularz w którym opisujemy jakieś wydarzenie i wprowadzamy dwie daty: rozpoczęcia i zakończenia. Jak sprawdzić czy pierwsza z dat poprzedza drugą? W takich sytuacjach najczęściej spotykaną sugestią jest "napisz własny walidator". Otóż wbrew pozorom takie rozwiązanie jest skomplikowane i niezbyt przejrzyste. Wynika to z założenia że walidator ma sprawdzać poprawność tylko jednego pola. "Zgodność haseł" czy "poprawna kolejność dat" nie są cechami jednego pola, a raczej całego formularza. Zatem bardziej logiczne wydaje się być rozwiązanie w którym to sam formularz (a nie poszczególne elementy) zajmie się walidacją.
W praktyce moja propozycja sprowadza się do zbudowania własnej metody isValid() formularza. Wyobraźmy sobie taką definicję:
<?php
class Application_Form_Register extends Zend_Form
{
public function init()
{
$this->addElement('text', 'email', array(
'label' => 'Adres e-mail:',
'required' => true,
'filters' => array(
'StringTrim'
),
'validators' => array(
'EmailAddress',
)
));
$this->addElement('password', 'password', array(
'label' => 'Hasło:',
'required' => true,
'filters' => array(
'StringTrim'
),
'validators' => array(
array('StringLength', false, array('min' => '6', 'max' => '40'))
)
));
$this->addElement('password', 'repeatPassword', array(
'label' => 'Powtórz hasło:',
'ignore' => true,
'required' => true,
'filters' => array(
'StringTrim'
),
'class' => 'text',
'validators' => array(
array('StringLength', false, array('min' => '6', 'max' => '40'))
)
));
// Tutaj ew. inne elementy
// ...
$this->addElement('submit', 'submit', array(
'label' => 'Rejestracja',
'class' => 'submit',
'ignore' => true
));
}
}
Teraz aby sprawdzić poprawność haseł wystarczy dodać jedną prostą metodę:
public function isValid($data)
{
$ret = parent::isValid($data);
if ($this->password->getValue() != $this->repeatPassword->getValue()) {
$this->repeatPassword->addError("Podane hasła nie zgadzają się.");
return false;
}
return $ret;
}
Prawda że jest to znacznie prostsze i bardziej wygodne niż pisanie własnego walidatora?
Dodatkowe wywołanie metody isValid() rodzica upewni nas że pozostałe pola również zostaną sprawdzone.