Zend Framework формы, декораторы и проверки: должен ли я вернуться к простому HTML?

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

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

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

Я сейчас понял, что серьезно рассматриваю возможность полностью отказаться от подхода Zend_Form_Element + Zend_Form_Decorator , но я не хочу потерять отличные варианты проверки.

В принципе, я хочу лучшего из обоих миров:

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

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

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

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

Я также считаю, что декораторы по умолчанию являются огромной болью. Я понимаю, почему они такие, каковы они есть, но я думаю, что «фактор неудобств» был сильно недооценен.

Во всяком случае, я бы рекомендовал использовать ViewScripts для ваших форм. Обратите внимание, что это не то же самое, что Views – вместо этого, 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.

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

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

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

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

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

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

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

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

Вот несколько декораторов, которые я использую в своих проектах, используя 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')), ); 

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

22,5. Zend_Filter_Input

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

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

Я использую 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'); } } 

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

Решение, которое я нашел наиболее простым и гибким, состоит в том, чтобы создать два файла формы: 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.

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

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

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

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

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

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

Редактировать / Комментировать верхний ответ by @Cal Jacobson.

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

 $this-element->getAction() 

должно быть

 $this->element->getAction() 

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