Формы, декораторы и валидация Zend Framework: стоит ли возвращаться к обычному HTML?

В настоящее время я работаю над довольно большим приложением, которое содержит множество форм.

До этого момента я всегда писал свои формы вручную и писал свою собственную логику проверки, но я решил, что пора начать использовать Zend_Form и его встроенные процедуры проверки.

Однако я постоянно сталкиваюсь со все большим количеством проблем, связанных с (отсутствием) гибкости, вызванной Zend_Form_Decorator. Простые задачи, такие как добавление дополнительной кнопки к одному элементу ввода, становятся невероятно сложными.

Теперь я достиг точки, когда серьезно подумываю о том, чтобы отказаться от _2 _ + Zend_Form_Decorator подход полностью, но я не хочу терять отличное варианты проверки.

По сути, я хочу лучшее из обоих миров:

  • Пишите формы так, как их видит конечный пользователь: в обычном HTML
  • Простое добавление проверок на стороне сервера в поля формы, не нарушая при этом стандартного поведения ZF

Возможное решение, которое я рассматриваю, - это написание форм как на стороне сервера, так и в представлениях. Это позволило бы мне легко проверять свои собственные формы, но (на мой взгляд, довольно большим) недостатком является то, что каждая форма должна определяться дважды, что кажется совершенно неправильным.

Есть ли какие-нибудь инструкции для этого? Испытывал ли кто-нибудь из вас то же самое, и если да, то как вы решили эти проблемы?

Очень хотелось бы услышать вашу точку зрения.


person Aron Rotteveel    schedule 14.08.2009    source источник


Ответы (10)


Я тоже считаю, что декораторы по умолчанию - это большая проблема. Я понимаю, почему они такие, но я думаю, что "фактор неудобства" был сильно недооценен.

В любом случае я бы рекомендовал использовать ViewScripts для ваших форм. Обратите внимание, что это не то же самое, что View - вместо этого ViewScripts явно упоминаются в вашем классе Form, действуют как своего рода «вспомогательные представления» и позволяют вам управлять макетом каждого элемента. В прошлом было довольно сложно найти примеры использования сценариев ViewScripts, но я постараюсь сделать что-нибудь полезное.

Во-первых, переопределите loadDefaultDecorators в своем классе формы:

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

Это будет ссылаться на ViewScript с именем bar.phtml, расположенный в / views / scripts / foo. Обратите внимание на разницу с учетом регистра в «ViewScript» и «viewScript» выше.

Затем вам нужно настроить декораторы, применяемые к каждому элементу, чтобы он отображался, но без раздражающих оболочек dt / dd. Например:

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

Наконец, вам нужно создать свой ViewScript, например:

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

Очевидно, это очень простой пример, но он показывает, как ссылаться на элементы формы и действие формы.

Затем в вашем представлении просто укажите ссылку и выведите свою форму как обычно. Таким образом, у вас будет гораздо более точный контроль над макетами форм, включая легкое добавление Javascript.

Я считаю, что этот подход решает оба ваших требования: вы можете создавать формы в простом HTML и при этом пользоваться механизмом проверки Zend Form.

person Cal Jacobson    schedule 14.08.2009
comment
Спасибо за Ваш ответ; хотя я уже знал о viewScripts, это, кажется, лучшее решение, отвечающее всем моим потребностям. - person Aron Rotteveel; 24.08.2009

Я использовал как можно больше компонентов Zend за последние 10 месяцев в большом проекте, и Zend_Form был самой большой проблемой в ***. Формы медленно обрабатываются, и их трудно сделать красивыми. Даже не заставляйте меня начинать с подформ. Я видел интересную статью под названием «масштабирование zend_form», но, похоже, она не очень помогает со скоростью рендеринга :(

Я думаю о том, чтобы сделать все свои формы, используя прямой HTML в представлении, и использовать Zend_Form только для проверки и фильтрации (не отрисовки). Либо так, либо я просто буду использовать Zend_Validate и Zend_Filter, вообще без аспекта формы.

Инструмент - это инструмент, только если он вам помогает. В противном случае это просто помеха.

person lo_fye    schedule 14.08.2009
comment
Это как раз мой опыт. Спасибо, что подтвердили, что это, вероятно, не только моя глупость делает это больно работать с этим :) - person Aron Rotteveel; 14.08.2009
comment
~ 3 года прошло с того момента, как вы ответили, у вас все еще есть эта мысль? Потому что в таком случае я разделяю ту же мысль, что и вы. - person jonathancardoso; 01.02.2012
comment
да, я все еще так чувствую. Я слышал, что ZF 2.0 (скоро) будет иметь рефакторинг Forms, поэтому я с нетерпением жду возможности попробовать это. А пока я использую Zend_Form как есть и пытаюсь стилизовать его, используя css, ИЛИ я использую Zend_Form только для проверки, но на самом деле я создаю html вручную. - person lo_fye; 01.02.2012
comment
Согласен, я полностью ненавижу Zend Framework. Он раздувается и пытается все делать. Насколько я понимаю, это Drupal фреймворков PHP. Сделано компанией, а не сообществом энтузиастов. Kohana, в настоящее время моя любимая. - person wesside; 11.06.2012

Вот что я узнал с Zend_Form:

Позвольте ему сделать это, и в конечном итоге это сэкономит вам массу строк кода.

Компромисс заключается в том, что вы в конечном итоге пишете больше CSS, чтобы все отображалось так, как вы хотите. Помните, что почти любой элемент HTML можно стилизовать так, чтобы он выглядел как угодно. По умолчанию Zend_Form предоставляет вам множество CSS-селекторов, которые можно сделать настолько конкретными (или широкими), насколько вам нужно. Я еще не видел случая, чтобы я не мог настроить декораторы по умолчанию в точности так, как я хотел.

Конечно, у меня есть большой уродливый CSS-файл, но, судя по моему опыту, в любом случае это, вероятно, будет большим уродливым CSS-файлом. Я предпочитаю не беспокоиться о кодировании / проверке / фильтрации / обработке форм конкретного приложения и т. Д., Но иметь дело с некоторыми специально стилизованными элементами в файле CSS.

Совет, если вы решите пойти по этому пути: убедитесь, что вы используете скрипт сброса стиля CSS < / а>

person Andy Baird    schedule 16.08.2009

Вот несколько декораторов, которые я использую в своих проектах с помощью Zend Form. Я считаю, что это достаточно просто для понимания.

$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')), );
person Dennis Day    schedule 06.09.2009

Если вам нужны валидаторы и фильтры без форм: Zend_Filter_Input

22.5. Zend_Filter_Input

Zend_Filter_Input предоставляет декларативный интерфейс для связывания нескольких фильтров и валидаторов, применения их к коллекциям данных и получения входных значений после того, как они были обработаны фильтрами и валидаторами. Значения по умолчанию возвращаются в экранированном формате для безопасного вывода HTML.

Хотя - Мое личное предложение - научиться создавать собственные декораторы и помощники просмотра. Zend_Form очень мощный инструмент, и у меня никогда не было проблем с попыткой расположить / украсить вещи. Даже при создании сложной таблицы разрешений и автоматической генерации столбцов и строк с помощью jQuery я обнаружил, что Zend_Form интерфейсы позволяют сэкономить время. Если у вас есть конкретный вопрос о том, как подойти к украшению чего-либо, я с радостью помогу. Откройте новый вопрос и прокомментируйте его здесь или что-то в этом роде ....

person gnarf    schedule 14.08.2009

Я использую Zend Framework около года и использовал Zend_Form только для одного из моих проектов (первого). Я отказался от Zend_Form после того, как потратил все 15 минут, пытаясь разместить свою ссылку «или Отменить». Хотя мне нравится интеграция.

Теперь я использую простые HTML-формы и использую Zend_Filter_Input в модели (Zend_Db_Table в большинстве случаев, но мне пришлось добавить уровень обслуживания в моем последнем проекте).

Пример фрагмента кода контроллера с использованием ZFI в модели. Обработка ошибок и общие методы проверки находятся в подклассе Zend_Db_Table, и мои классы расширяют его.

Помощник представления форматирует массив сообщений об ошибках.

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');
    }
}
person Ekerete    schedule 14.08.2009
comment
Спасибо за Ваш ответ. Не могли бы вы рассказать, как вы проверяете свои формы и показываете клиенту сообщения об ошибках? - person Aron Rotteveel; 14.08.2009
comment
Я создаю экземпляр ZFI в модели, а также имею свойство удерживать ошибки в случае сбоя проверки. Ниже я опубликую фрагмент кода контроллера. - person Ekerete; 14.08.2009
comment
Я объединил свои два сообщения, поэтому мой фрагмент кода приведен выше. Удаляю повторяющуюся запись. - person Ekerete; 15.08.2009

Я второй, о чем упоминал lo_fye. По моему опыту, формы Zend неуклюжи и плохо продуманы.

Решение, которое я нашел наиболее простым и гибким, - это создать два файла формы: 1. класс формы, который инициализирует элементы формы, а затем сценарий представления для отображения элементов формы. В моем классе формы я отключаю все декораторы за вычетом самого элемента формы. например: -> removeDecorator ('HtmlTag') -> removeDecorator ('DtDdWrapper') -> removeDecorator ('Label') -> removeDecorator ('Errors');

Затем в конце конструктора, который инициализирует элементы формы, передайте сценарий представления: $ this-> setDecorators (array (array ('ViewScript', array ('viewScript' => 'path / to / script_form.phtml')) ));

В сценарии просмотра я форматирую форму именно так, как мне нравится, тогда где поле ввода (например,) будет просто отображать этот элемент: $ this-> element-> form_element_id. И обратите внимание, я удаляю украшения ошибок и просто беру стек ошибок и отображаю его так, как я думаю.

Обратной стороной является создание сценария представления для каждой формы или самостоятельная сборка какой-либо системы многократного использования, что требует дополнительной работы. Но, в конце концов, гораздо проще создавать формы, которые вписываются в ваш макет, imo.

person mardala    schedule 08.02.2010

Вы можете использовать Zend Form и самостоятельно сгенерировать HTML :) Вам просто нужно отслеживать изменения и обрабатывать элементы формы одинаково в HTML и ZF :)

person Tomáš Fejfar    schedule 15.08.2009
comment
Zend Forms пытается избавиться от этих изменений в двух местах! Это стоит обучения (надеюсь, я все еще на нем) - person Matthew; 12.04.2010
comment
Абсолютно согласен ! Я как раз отвечал на вопрос! :) - person Tomáš Fejfar; 12.04.2010

Краткий ответ: используйте Zend_Form только для проверки и фильтрации, а также используйте свои простые старые сценарии представления для визуализации формы так, как вы хотите.

Длинный ответ: я пришел к выводу, что не стоит использовать Zend_Form для генерации HTML формы. По крайней мере, в компании я работаю. Но почему?

Это просто, я не хочу создавать класс (или использовать хак) просто для того, чтобы «спокойно» добавить ссылку в div внутри моей формы. Я не хочу создавать несколько декораторов только для того, чтобы добавить функциональность, которую можно было бы легко добавить с помощью простого HTML, и, что наиболее важно, дизайнеры, которые работают с нами, не хотят редактировать один (или два или более) класса [ов] только для делают свою работу.

Мы продолжаем использовать Zend_Form, но только для проверки и фильтрации наших форм. И не порождать их.

Я знаю, что многие не согласятся с моими аргументами, но это всего лишь мнение человека, который провел бессонные ночи благодаря Zend_Fom.

person jonathancardoso    schedule 01.02.2012
comment
JCM, я думаю, в таком случае кто-то может определить проверки / фильтры с помощью Zend_Filter_Input. Я думаю, что нет смысла использовать zend_form для валидации только в том случае, если элементы формы обязательно должны поступать только из html. - person Rakesh Lamp Stack; 15.01.2015

Изменить / прокомментировать верхний ответ @Cal Jacobson.

Невозможно редактировать, потому что в изменении недостаточно символов, нельзя комментировать из-за недостаточного количества реплик, но ...

$this-element->getAction()

должно быть

$this->element->getAction()

Я уверен, что OP знает это, но исправление позволит избежать ошибки при попытке напрямую использовать код в ответе.

person NaNuk    schedule 17.07.2012