Я думаю, что нашел возможное решение, оно включает передачу массива элементов Zend Form в метод Zend Form :: __ construct () . Конструктор принимает массив параметров, один из которых называется " elements ". Посмотрите на исходный код в библиотеке Zend Framework.
Я написал новый закрытый метод внутри контроллера, который называется buildSurveyForm (). Примечание: объект, передаваемый в качестве параметра, создается из огромного SQL-запроса с полудюжиной операторов JOIN, извлекающих данные из нескольких таблиц (опросов, вопросов, ответов и т. Д.) В базе данных. Один из общедоступных атрибутов этого класса состоит из массива вопросов, хранящихся в виде объектов (также с общедоступными методами / атрибутами и т. Д.). То же самое для ответов. Код для создания этих классов довольно тривиален и неуместен здесь.
Вот код внутри контроллера опроса. Я скопировал / вставил и отредактировал / уронил несколько строк, чтобы сделать это намного яснее:
private function buildSurveyForm(MyApp_Object_Survey $survey)
{
foreach ($survey->questions as $question)
{
$element = new Zend_Form_Element_MultiCheckbox($question->order);
$element->addMultiOptions($question->getAnswersLabels());
$element->setName($question->order);
$element->setLabel($question->title);
$elements[] = $element;
}
// Here's the trick :
$formOptions = array('elements' => $elements);
$surveyForm = new MyApp_Survey_Form($formOptions);
$urlHelper = $this->_helper->getHelper('url');
$surveyForm->setAction($urlHelper->url(array(
'controller' => 'survey',
'action' => 'vote'),
'default'
));
$surveyForm->setMethod('post');
$this->_forms['survey'] = $surveyForm;
return $this->_forms['survey'];
}
Класс MyApp Survey Form содержит только кнопку Submit в методе init (). Динамически генерируемые элементы с кодом выше добавляются ДО этой кнопки отправки (что является неожиданным, но полезным). Этот класс просто расширяет Zend_Form.
Затем в контроллере съемки / действии просмотра:
public function viewAction()
{
$surveyModel = $this->_model['survey'];
$survey = $surveyModel->getFullSurvey($this->_getParam('id'));
$survey = new MyApp_Object_Survey($survey);
// Calls above private method :
$surveyForm = $this->buildSurveyForm($survey);
$this->view->assign(array(
'surveyForm' => $surveyForm,
));
}
Добавление фильтров, валидаторов и декораторов для элементов формы теперь тривиально. Мое предложение немного грязное, но я думаю, оно выполнит свою работу. Я добавлю новое предложение, если найду что-то более элегантное. Не стесняйтесь размещать различные ответы / решения.