Zend Framework forms, decorators and validation: czy powinienem wrócić do zwykłego HTML?

Obecnie pracuję nad dość dużą aplikacją, która zawiera wiele formularzy.

Do tej chwili, zawsze pisałem swoje formularze ręcznie i pisałem własną logikę walidacji, ale zdecydowałem, że nadszedł czas, abym zaczął używać Zend_Form i jego wbudowanych procedur walidacji.

Jednak wciąż natykam się na coraz więcej problemów dotyczących (braku) elastyczności powodowanej Zend_Form_Decorator. Proste zadania, takie jak dodanie dodatkowego przycisku do pojedynczego elementu wejściowego stają się niezwykle trudne zadania.

Doszedłem do punktu, w którym poważnie rozważam porzucenie Zend_Form_Element + Zend_Form_Decorator podejście całkowicie, ale nie chcę stracić doskonałe opcje walidacji.

W zasadzie chcę tego, co najlepsze z obu światów:

  • zapis formularzy tak, jak widzi je użytkownik końcowy: w prostym HTML
  • Łatwe dodawanie walidacji po stronie serwera do pól formularza bez łamania zbyt wielu standardowe zachowanie ZF

Możliwym rozwiązaniem, które rozważam, jest pisanie formularzy zarówno po stronie serwera, jak i w widokach. To pozwoliłoby mi łatwo zweryfikować moje własne formy, ale (w moich oczach dość duży) minusem jest to, że każdy formularz powinien być zdefiniowany dwa razy, co po prostu wydaje się błędne.

Czy są jakieś wytyczne, aby to zrobić? Czy ktoś z was doświadczył tego samego, a jeśli tak, to jak rozwiązaliście te problemy?

Bardzo chciałbym usłyszeć Twoje uwagi widok.
Author: Aron Rotteveel, 2009-08-14

10 answers

Ja też uważam, że domyślne dekoratory to ogromny ból. Rozumiem Dlaczego są tacy, jakimi są, ale myślę, że "czynnik niedogodności" został rażąco niedoceniany.

W każdym razie, polecam użycie ViewScripts dla formularzy. Zauważ, że nie są to te same widoki-zamiast tego, Skrypty widoków są odwoływane jawnie w klasie formularza, działają jako" pod-widok " i pozwalają kontrolować układ każdego elementu. Przykłady użycia ViewScripts były nieco trudne do znalezienia w przeszłości, ale postaram się podjąć próbę dostarczenia czegoś użytecznego.

Najpierw Obejmij loadDefaultDecorators w klasie form:

public function loadDefaultDecorators() {
     $this->setDecorators(
         array(
             array('ViewScript', 
                 array('viewScript' => 'foo/bar.phtml')
             )
          )
      );        
} 

Spowoduje odwołanie się do ViewScript o nazwie bar.phtml znajduje się w /views/scripts/foo . Zwróć uwagę na różnice uwzględniające wielkość liter w "ViewScript" i "viewScript" powyżej.

Następnie musisz dostosować dekoratory zastosowane do każdego elementu, aby upewnić się, że jest wyświetlany, ale bez irytujące opakowania dt / dd. Na przykład:

$baz = new Zend_Form_Element_Text('bazInput');
$baz->setDecorators(array('ViewHelper','Errors')); 

Na koniec musisz zbudować swój ViewScript, na przykład:

<form method="post" action="<?php echo $this-element->getAction() ?>">
    <table>
        <tr>
            <td><label for="bazInput">Baz:</label></td>
            <td><?php echo $this->element->bazInput ?></td>
        </tr>
    </table>
    <input type="submit" value="Submit Form" />
</form>

Oczywiście jest to bardzo prosty przykład, ale ilustruje, jak odwoływać się do elementów formularza i akcji formularza.

Następnie, Twoim zdaniem, po prostu odwołaj się i wyprowadź swój formularz jak zwykle. W ten sposób możesz mieć znacznie lepszą kontrolę nad układami formularzy - aby łatwo dodać Javascript.

Wierzę, że takie podejście rozwiązuje oba Twoje wymagania: ty potrafi budować formularze w prostym HTML i nadal korzystać z mechanizmu walidacji formularzy Zend.

 21
Author: Cal Jacobson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-17 18:35:12

Używałem jak największej liczby komponentów Zend w ciągu ostatnich 10 miesięcy, w dużym projekcie, a Zend_Form był największym bólem w***. Formy są powolne w renderowaniu i trudne do upiększenia. Nawet nie każ mi zaczynać od formularzy podrzędnych. Widziałem ciekawy artykuł o nazwie "skalowanie zend_form", ale nie pomogło to zbytnio z szybkością renderowania: (

Zastanawiam się nad stworzeniem wszystkich moich formularzy używając prostego HTML w widoku i tylko używając Zend_Form, aby zrobić Walidacja i filtrowanie (nie renderowanie). Albo To, albo po prostu użyję Zend_Validate i Zend_Filter, bez aspektu formy.

Narzędzie jest tylko narzędziem, jeśli ci pomaga. W przeciwnym razie, to tylko przeszkoda.

 9
Author: lo_fye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 14:02:58

Oto czego się nauczyłem z Zend_Form:

Niech to zrobi, a zaoszczędzi Ci mnóstwo linii kodu na dłuższą metę.

Kompromis polega na tym, że piszesz więcej CSS, aby rzeczy wyświetlały się tak, jak chcesz. Pamiętaj, że prawie każdy element HTML może być stylizowany tak, aby wyglądał jak cokolwiek. Domyślnie, Zend_Form daje Ci mnóstwo selektorów CSS, które możesz uzyskać tak specyficznie (lub szeroko), jak potrzebujesz. Jeszcze nie widziałem przypadku, w którym nie mogłem pracować domyślnych dekoratorów w dokładnie takie, jakie chciałem.

Przyznaję, że mam duży, brzydki plik CSS, ale z mojego doświadczenia wynika, że w końcu i tak byłby to duży, brzydki plik CSS. Biorę kompromis nie martwiąc się o kodowanie/walidację/filtrowanie/obsługę/itp, ale zajmując się niektórymi specjalnie stylizowanymi elementami w pliku CSS.

Wskazówka jeśli zdecydujesz się na tę trasę: upewnij się, że używasz skrypt reset stylu CSS

 4
Author: Andy Baird,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-16 06:31:29

Oto kilka dekoratorów, których używam w moich projektach używając Zend Form. Te, jak sądzę, są wystarczająco proste do zrozumienia.

$stdRowDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td', 'width' => '200')), array('Label', array('escape' => false, 'class' => 'zfFormLabel', 'tag' => 'td')), array(array('row'=>'HtmlTag'), array('tag'=>'tr')));
$startRowDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td')), array('Label', array('escape' => false, 'tag' => 'td', 'class' => 'zfFormLabel')), array(array('row'=>'HtmlTag'), array('tag'=>'tr', 'openOnly'=>true)));
$startRowOpenOnlyDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td', 'openOnly'=>true)), array('Label', array('escape' => false, 'class' => 'zfFormLabel', 'tag' => 'td')), array(array('row'=>'HtmlTag'), array('tag'=>'tr', 'openOnly'=>true)));
$midRowDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td')),array('Label', array('escape' => false, 'class' => 'zfFormLabel', 'tag' => 'td')));
$midRowCloseOnlyDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td', 'closeOnly'=>'true')),array('Label', array('escape' => false, 'class' => 'zfFormLabel', 'tag' => 'td')));
$midRowCloseOnlyNoLabelDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td', 'closeOnly'=>'true')));
$endRowDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td')), array('Label', array('escape' => false, 'class' => 'zfFormLabel', 'tag' => 'td')), array(array('row'=>'HtmlTag'), array('tag'=>'tr', 'closeOnly'=>'true')));
$endRowCloseOnlyNoLabelDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td', 'closeOnly'=>'true')), array(array('row'=>'HtmlTag'), array('tag'=>'tr', 'closeOnly' => 'true')));
$buttonEndRowDec = array('ViewHelper', 'Description', 'Errors', array(array('data'=>'HtmlTag'), array('tag' => 'td', 'colspan'=>'2', 'align'=>'center')), array(array('row'=>'HtmlTag'), array('tag'=>'tr', 'closeOnly'=>'true')));
$buttonDecorators = array('ViewHelper', array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element')), array(array('label' => 'HtmlTag'), array('tag' => 'td', 'placement' => 'prepend')), array(array('row' => 'HtmlTag'), array('tag' => 'tr')), );
 4
Author: Dennis Day,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-29 05:13:58

Jeśli chcesz walidatorów i filtrów bez formularzy: Zend_Filter_Input

22.5. Zend_Filter_Input

Zend_Filter_Input zapewnia deklaratywny interfejs do kojarzenia wiele filtrów i walidatorów, zastosuj ich do zbierania danych oraz do pobiera wartości wejściowe po ich zostały przetworzone przez filtry i walidatorów. Wartości są zwracane w domyślnie dla bezpiecznego formatu ucieczki Wyjście HTML.

Chociaż-moją osobistą sugestią jest nauczenie się rzemiosła niestandardowych dekoratorów i pomocników widoku. Zend_Form jest bardzo potężny i nigdy nie miałem problemów z ułożeniem / udekorowaniem rzeczy. Nawet podczas budowania złożonej tabeli uprawnień i automatycznego generowania kolumn i wierszy za pomocą jQuery-znalazłem interfejsy Zend_Form oszczędność czasu. Jeśli masz konkretne pytanie, jak podejść do dekoracji czegoś chętnie pomogę. Otwórz nowe pytanie i skomentuj je tutaj lub coś....
 2
Author: gnarf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 19:27:47

Używam Zend Framework od około roku i używałem tylko Zend_Form dla jednego z moich projektów (pierwszego). Zrezygnowałem z Zend_Form po tym, Jak spędziłem wszystkie 15 minut próbując ustawić mój link "lub Anuluj". Uwielbiam jednak integrację.

Używam teraz prostych formularzy HTML i używam Zend_Filter_Input w modelu (Zend_Db_Table w większości przypadków, ale musiałem dodać warstwę usług w moim ostatnim projekcie).

Przykładowy fragment kodu kontrolera wykorzystującego ZFI w modelu. Obsługa błędów i wspólna Walidacja metody są w podklasie Zend_Db_Table i moje klasy ją rozszerzają.

Pomocnik widoku formatuje tablicę komunikatów o błędach.

if ($this->_request->isPost()) {
    $data = $this->_request->getPost();
    $event = new Default_Model_DbTable_Event();         
    $event->createRow($data)->save();

    if ($event->hasErrors()) {
        $this->view->errors = $event->getErrorMessages();
        $this->view->event = $data;
    } else {
        $this->_redirect('events');
    }
}
 2
Author: Ekerete,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 20:00:12

Popieram to, o czym wspomniał lo_fye. Z mojego doświadczenia wynika, że formy Zend są niezgrabne i nie są dobrze przemyślane.

Najprostszym i najbardziej elastycznym rozwiązaniem jest utworzenie dwóch plików formularzy, 1. Klasa formularza, która inicjalizuje Elementy formularza, a następnie skrypt widoku do wyświetlania elementów formularza. W mojej klasie formy wyłączam wszystkie dekoratory, minus rzeczywisty element formy. np.: ->removeDecorator ('HtmlTag') - >removeDecorator ('DtDdWrapper') ->removeDecorator ('Label') - >removeDecorator ('Errors');

Następnie na końcu konstruktora inicjującego Elementy formularza przekaż skrypt widoku: $this - > setDecorators(array ('ViewScript', array ('viewScript' = > 'ścieżka/do/script_form.phtml')));

W skrypcie widoku formatuję formularz dokładnie tak, jak mi się podoba, wtedy pole wejściowe (np.) będzie wyświetlało tylko ten element: $this - > element - > form_element_id. I zauważ, że usuwam dekoracje błędów i po prostu chwytam stos błędów i wyświetlam go tak, jak myślę, że powinien.

Minusem jest to, że stworzyłbyś skrypt widoku dla każdego formularza lub sam zbudowałeś jakiś System wielokrotnego użytku, więc dodatkowa praca. Ale w końcu znacznie łatwiej jest zaprojektować formularze pasujące do twojego układu, imo.

 2
Author: mardala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-08 05:44:28

Możesz użyć Zend Form i samemu wygenerować HTML:) musisz tylko śledzić zmiany i śledzić elementy formularza tak samo w HTML i ZF:)

 1
Author: Tomáš Fejfar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-15 14:44:03

Krótka odpowiedź: używaj Zend_Form tylko do sprawdzania poprawności i filtrowania, i używaj starych skryptów widoku, aby renderować formularz tak, jak chcesz.

Długa odpowiedź: doszedłem do wniosku, że nie warto używać Zend_Form do generowania HTML formularza. Przynajmniej w firmie, w której pracuję. Ale dlaczego?

To proste, nie chcę tworzyć klasy (lub używać hacka) tylko po to, aby "spokojnie" dodać link w div wewnątrz mojego formularza. Nie chcę tworzyć wielu dekoratorzy tylko po to, aby dodać funkcjonalność, którą można łatwo dodać za pomocą prostego HTML, a co najważniejsze, projektanci, którzy pracują z nami, nie chcą edytować jednej (lub dwóch lub więcej) klas[es] tylko po to, aby ich praca.

Nadal Używamy Zend_Form, ale tylko do walidacji i filtrowania naszych formularzy. I nie po to, by je generować.

Wiem, że wielu nie zgodzi się z moimi argumentami, ale to tylko opinia kogoś, kto miał nieprzespane noce zrobione dzięki Zend_Fom.

 1
Author: JCM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-22 18:22:47

Edit / Comment on top answer by @ Cal Jacobson.

Nie można edytować, ponieważ zmiana jest niewystarczająca znaki, nie można komentować z powodu niewystarczającej rep ale...

$this-element->getAction()

Powinno być

$this->element->getAction()

Jestem pewien, że OP wie o tym, ale korekta uniknie błędu podczas próby bezpośredniego użycia kodu w odpowiedzi.

 0
Author: NaNuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-17 12:49:55