Zend_Form: walidacja rozbudowanych formularzy

by Mateusz Tymek — on Zend Framework, PHP

Head's up! This post was written back in 2010 and is very likely to contain outdated information.

Walidacja rozbudowanych formularzy

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.


comments powered by Disqus