18.2. Szybki start z Zend_Form

Ten przewodnik opisuje podstawy tworzenia, weryfikacji oraz renderowania formularzy za pomocą komponentu Zend_Form.

18.2.1. Tworzenie obiektu formularza

Tworzenie obiektu formularza jest bardzo proste: po prostu utwórz egzemplarz klasy Zend_Form:

$form = new Zend_Form;

        

W zaawansowanych przypadkach możesz rozszerzyć klasę Zend_Form, ale dla prostych formularzy możesz utworzyć i skonfigurować formularz za pomocą obiektu Zend_Form.

Jeśli chcesz określić akcję oraz metodę wywołania formularza, możesz to zrobić za pomocą metod dostępowych setAction() oraz setMethod():

$form->setAction('/resource/process')
     ->setMethod('post');

        

Powyższy kod ustawia akcję formularza na adres URL "/resource/process" oraz metodę wykonania formularza na HTTP POST. Będzie to wzięte pod uwagę podczas renderowania formularza.

Możesz ustawić dodatkowe atrybuty dla znacznika <form> używając metod setAttrib() lub setAttribs(). Przykładowo jeśli chcesz ustawić idetyfikator, utaw atrybut "id":

$form->setAttrib('id', 'login');

        

18.2.2. Dodawanie elementów do formularza

Formularz jest bezużyteczny jeśli nie posiada elementów. Komponent Zend_Form posiada kilkanaście domyślnych elementów które mogą być renderowane do postaci XHTML za pomocą klas pomocniczych Zend_View. Te elementy to:

  • button (przycisk)

  • checkbox (pole wyboru lub wiele pól za pomocą multiCheckbox)

  • hidden (pole ukryte)

  • image (obrazek)

  • password (hasło)

  • radio (pole opcji)

  • reset (przycisk resetujący)

  • select (lista zwykła oraz lista wielokrotnego wyboru)

  • submit (przycisk wysyłający)

  • text (pole tekstowe)

  • textarea (wieloliniowe pole tekstowe)

Masz dwie możliwości dodania elementów do formularza: możesz utworzyć egzemplarze konkretnych elementów i przekeazać je do obiektu, lub po prostu przekazać typy elementów i pozwolić obiektowi Zend_Form na atomatyczne utworzenie egzemplarzy obiektów określonego typu.

Kilka przykładów:

// Utwórz egzemplarz elementu i przekaż go do obiektu formularza:
$form->addElement(new Zend_Form_Element_Text('username'));

// Przekaż typ elementu do obiektu:
$form->addElement('text', 'username');

        

Domyślnie elementy te nie posiadają filtrów i weryfikatorów. Oznacza to że musisz skonfigurować dla swoich elementów chociaż weryfikatory i opcjonalnie filtry. Możesz to zrobić (a) zanim przekażesz element do formularza, (b) za pomocą opcji konfiguracyjnych przekazanych podczas tworzenia elementu poprzez obiekt Zend_Form lub (c) pobierając istniejący element z obiektu formularza i konfigurowanie go.

Przyjrzyjmy się wpierw tworzeniu weryfikatorów dla konkretnego egzemplarza elementu. Możesz przekazać obiekt Zend_Validate_* lub nazwę weryfikatora który ma być  użyty:

$username = new Zend_Form_Element_Text('username');

// Przekaż obiekt Zend_Validate_*:
$username->addValidator(new Zend_Validate_Alnum());

// Przekaż nazwę weryfikatora:
$username->addValidator('alnum');

        

Jeśli używasz drugiego sposobu, a weryfikator przyjmuje argumenty konstruktora, możesz je pzekazać w tablicy jako trzeci parametr:

// Przekaż wzór
$username->addValidator('regex', false, array('/^[a-z]/i'));

        

(Drugi parametr jest używany aby określić czy niepowodzenie w weryfikacji ma przerwać następne weryfikacje czy nie; domyślnie ma wartość false.)

Możesz także chcieć określić element jako wymagany. Zrobisz to używając metody dostępowej lub przekazując opcję podczas tworzenia elementu. Oto pierwszy sposób:

// Ustaw element jako wymagany:
$username->setRequired(true);

        

Gdy element jest wymagany, weryfikator 'NotEmpty' dodawany jest na sam początek łańcucha weryfikatorów, dzięki czemu możemy być pewni że element będzie posiadał wartość.

Filtry są rejestrowane w taki sam sposób jak weryfikatory. Aby pokazać jak działają, dodajmy filtr zamieniający znaki na małe litery:

$username->addFilter('StringtoLower');

        

Finalnie konfiguracja elementu może wyglądać tak:

$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]/'))
         ->setRequired(true)
         ->addFilter('StringToLower');

// lub bardziej zwięźle:
$username->addValidators(array('alnum',
        array('regex', false, '/^[a-z]/i')
    ))
    ->setRequired(true)
    ->addFilters(array('StringToLower'));

        

Tworzenie obiektu dla każdego z elementów formularza może być czasem nieco kłopotliwe. Spróbujmy zatem użyć sposobu (b) przedstawionego wyżej. Kiedy tworzymy nowy element używając metody Zend_Form::addElement() jako fabryki, możemy opcjonalnie przekazać opcje konfiguracyjne. Obejmuje to także konfigurację filtrów i weryfikatorów. Aby to zrobić użyj kodu:

$form->addElement('text', 'username', array(
    'validators' => array(
        'alnum',
        array('regex', false, '/^[a-z]/i')
    ),
    'required' => true,
    'filters'  => array('StringToLower'),
));

        
[Notatka] Notatka

Jeśli konfigurujesz elementy w kilku miejscach używając tych samych opcji, możesz rozważyć stworzenie własnej klasy rozszerzającej klasę Zend_Form_Element i następnie użyć tej klasy do tworzenia własnych elementów; może to oszczędzić nieco pracy.

18.2.3. Renderowanie formularza

Renderowanie formularza jest proste. Większość elementów używa do tego klas pomocniczych Zend_View, więc potrzebny będzie do tego także obiekt widoku. Masz dwie możliwości: użycie metody formularza render() lub po prostu wyświetlenie formularza za pomocą konstrukcji echo.

// Jawnie wywołaj metodę render() i przekaż pcjonalny obiekt widoku:
echo $form->render($view);

// Zakładając że obiekt widoku został wcześniej ustawiony za pomocą setView():
echo $form;

        

Domyślnie obiekty Zend_Form oraz Zend_Form_Element użyją obiektu widoku zainicjowanego w obiekcie ViewRenderer, co oznacza, że nie musisz go ręcznie ustawiać gdy używasz wzorca MVC Zend Framework. Renderowanie formularza w skrypcie widoku jest wtedy bardzo proste:

<?= $this->form ?>

        

Zend_Form używa "dekoratorów" do przeprowadzania renderowania. Te dekoratory mogą zastępować zawartość, dodawać zawartość na początku lub na końcu, a także mieć pełny wgląd w element przekazany do nich. Możesz użyć kilku dekoratorów aby uzyskać wymagany efekt. Domyślnie Zend_Form_Element używa czterech dekoratorów aby wygenerować kod wyjściowy; wygląda to w taki sposób:

$element->addDecorators(array(
    'ViewHelper',
    'Errors',
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));

        

(Gdzie <HELPERNAME> jest nazwą klasy pomocniczej widoku, która ma być użyta. Może ona różnić się dla różnych elementów.)

Układ dekoratorów przedstawiony powyżej generuje następujący kod:

<dt><label for="username" class="required">Username</dt>
<dd>
    <input type="text" name="username" value="123-abc" />
    <ul class="errors">
        <li>'123-abc' has not only alphabetic and digit characters</li>
        <li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
    </ul>
</dd>

        

(Jednak kod jest inaczej sformatowany.)

Możesz zmienić dekoratory używane przez element jeśli chcesz mieć inny wyjściowy kod XHTML; zobacz rozdział poświęcony dekoratorom aby uzyskać więcej informacji.

Formularz przechodzi poprzez wszystkie elementy i zawiera je wewnątrz znacznika HTML <form>. Akcja i metoda wysyłania formuarza które podałeś podczas jego konfigurowania zostaną dołączone do znacznika<form>, tak samo jak inne atrybuty ustawione za pomocą metody setAttribs().

Formularz przechodzi przez elementy w takiej kolejności w jakiej były one zarejestrowane lub jeśli twój element zawiera odpowiedni atrybut, zostanie on użyty w celu ustalenia kolejności. Możesz ustawiać kolejność elementów używając metody:

$element->setOrder(10);

        

Lub przekazując kolejność jako opcję podczas tworzenia elementu:

$form->addElement('text', 'username', array('order' => 10));

        

18.2.4. Sprawdzanie poprawności formularza

Po tym jak formularz zostanie wysłany, musisz sprawdzić czy pomyślnie przeszedł weryfikację. Każdy element jest sprawdzany w oparciu o podane dane; jeśli nie ma klucza odpowiadającego nazwie elementu, a element jest oznaczony jako wymagany, weryfikacja zostanie przeprowadzona w oparciu o pustą wartość (null).

Skąd pochodzą dane? Możesz użyć tablic $_POST, $_GET lub dowolnych innych źródeł danych (np. żądań do serwisów web):

if ($form->isValid($_POST)) {
    // dane są poprawne
} else {
    // dane nie są poprawne
}

        

Jeśli używasz żądań AJAX, możesz potrzebować przeprowadzić weryfikację pojedynczego elementu lub grupy elementów. Metoda isValidPartial() częściowo weryfikuje formularz. W przeciwieństwie do metody isValid(), nie przeprowadza ona weryfikacji pól dla elementów których wartości nie zostały podane:

if ($form->isValidPartial($_POST)) {
    // dane we wszystkich elementach pomyślnie przyszły weryfikację
} else {
    // jeden lub więcej elementów nie przeszło poprawnie weryfikacji
}

        

Do częściowej weryfikacji formularza możemy także użyć metody processAjax(). W przeciwieństwie do metody isValidPartial(), zwraca ona łańcuch znaków w formacie JSON zawierający informacje o błędach.

Zakładając że elementy zostały zweryfikowane i są poprawne, możesz pobrać przefiltrowane wartości:

$values = $form->getValues();

        

Jeśli potrzebujesz niefiltrowanych wartości, użyj:

$unfiltered = $form->getUnfilteredValues();

        

18.2.5. Pobieranie informacji o błędach

Twój formularz nie przeszedł weryfikacji? W większości przypadków możesz po prostu powtórnie renderować formularz, a błędy zostaną wyświetlone używając dekoratorów:

if (!$form->isValid($_POST)) {
    echo $form;

    // lub przekaż go do obiektu widoku i renderuj widok
    $this->view->form = $form;
    return $this->render('form');
}

        

Dostępne są dwie metody do sprawdzania błędów. Metoda getErrors() zwraca tablicę asocjacyjną zawierającą informacje o błędach w postaci nazwa elementu / kody (gdzie kody są tablicami kodów błędów). Metoda getMessages() zwraca tablicę asocjacyjną zawierającą informacje o błędach w postaci nazwa elementu / komunikaty (gdzie komunikaty są asocjacyjną tablicą w postaci kod / komunikat). Jeśli dany element nie zawiera błędów, nie będzie zawarty w tablicy.

18.2.6. Złożenie tego w całość

Zbudujmy prosty formularz logowania. Potrzebne będą elementy:

  • nazwa użytkownika

  • hasło

  • przycisk wysyłający

Dla zobrazowania załóżmy że poprawna nazwa użytkownika powinna składać się jedynie ze znaków alfanumerycznych, powinna zaczynać się od litery, jej długość powinna zawierać się między 6 a 12 znakami; litery powinny zostać zamienione na małe. Hasło musi składać się minimalnie z 6 znaków. Wartość przycisku wysyłającego formularz zignorujemy, więc nie musi być ona weryfikowana.

Użyjemy metod konfiguracyjnych obiektu Zend_Form do zbudowania formularza:



$form = new Zend_Form();
$form->setAction('/user/login')
     ->setMethod('post');

// Utwórz i skonfiguruj element zawierający nazwę użytkownika:
$username = $form->createElement('text', 'username');
$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]+/'))
         ->addValidator('stringLength', false, array(6, 20))
         ->setRequired(true)
         ->addFilter('StringToLower');

// Utwórz i skonfiguruj element zawierający hasło:
$password = $form->createElement('password', 'password');
$password->addValidator('StringLength', false, array(6))
         ->setRequired(true);

// Dodaj elementy do formularza:
$form->addElement($username)
     ->addElement($password)
     // użyj metody addElement() jako fabryki tworzącej przycisk 'Zaloguj':
     ->addElement('submit', 'login', array('label' => 'Zaloguj'));

        

Następnie utworzymy kontroler obsługujący formularz:

class UserController extends Zend_Controller_Action
{
    public function getForm()
    {
        // formularz utwórz jak wyżej
        return $form;
    }

    public function indexAction()
    {
        // renderuj plik user/form.phtml
        $this->view->form = $this->getForm();
        $this->render('form');
    }

    public function loginAction()
    {
        if (!$this->getRequest()->isPost()) {
            return $this->_forward('index');
        }
        $form = $this->getForm();
        if (!$form->isValid($_POST)) {
            // Nieudana weryfikacja; wyświetl formularz
            $this->view->form = $form;
            return $this->render('form');
        }
        
        $values = $form->getValues();
        // spróbuj uwierzytelnić
    }
}

        

Utworzymy skrypt widoku wyświetlający formularz:

<h2>Zaloguj się:</h2>
<?= $this->form ?>

        

Jak zauważysz w kodzie kontrolera, może być wymagane jeszcze trochę pracy: jeśli wysłane dane będą poprawne, powinieneś przeprowadzić uwierzytelnienie używając np. klasy Zend_Auth.

18.2.7. Użycie oiektu Zend_Config

Wszystkie klasy Zend_Form można skonfigurować za pomocą komponentu Zend_Config; możesz przkazać obiekt klasy Zend_Config do konstruktora lub przekazać go za pomocą metody setConfig(). Spójrzmy jak możemy utworzyć powyższy formularz używając pliku INI. Wpierw weźmy pod uwagę zalecenia i umieśćmy konfigurację w sekcjach odnoszących się do typu wdrożenia aplikacji i skupmy się na sekcji 'development'. Następnie ustawmy utwórzmy sekcję dla danego kontrolera ('user'), oraz klucz dla formularza ('login'):

[development]
; ogólna konfiguracja formularza
user.login.action = "/user/login"
user.login.method = "post"

; nazwa użytkownika
user.login.elements.username.type = "text"
user.login.elements.username.options.validators.alnum.validator = "alnum"
user.login.elements.username.options.validators.regex.validator = "regex"
user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
user.login.elements.username.options.validators.strlen.validator = "StringLength"
user.login.elements.username.options.validators.strlen.options.min = "6"
user.login.elements.username.options.validators.strlen.options.max = "20"
user.login.elements.username.options.required = true
user.login.elements.username.options.filters.lower.filter = "StringToLower"

; hasło
user.login.elements.password.type = "password"
user.login.elements.password.options.validators.strlen.validator = "StringLength"
user.login.elements.password.options.validators.strlen.options.min = "6"
user.login.elements.password.options.required = true

; przycisk wysyłający
user.login.elements.submit.type = "submit"

        

Możesz to przekazać do konstruktora obiektu formularza:

$config = new Zend_Config_Ini($configFile, 'development');
$form   = new Zend_Form($config->user->login);

        

i cały formularz zostanie w ten sposób zdefiniowany.

18.2.8. Podsumowanie

Dzięki temu przewodnikowi powinieneś nauczyć się wykorzystywać moc i elastyczność komponentu Zend_Form. Teraz możesz przeczytać bardziej szczegółowe informacje!