# Szybki start z Zend_Form

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

## 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');

## 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'),
    ));

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.

## 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));

## 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();

## 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.

## 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`.

## 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.

## Podsumowanie

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