我想我找到了一个可能的解决方案,它涉及将Zend Form 元素数组传递给Zend Form::__construct()方法。构造函数采用一组选项,其中一个称为“元素”。查看 Zend Framework 库中的源代码。
我在控制器中编写了一个新的私有方法,称为 buildSurveyForm()。注意:作为参数传递的对象是由一个带有六个 JOIN 语句的巨大 SQL 查询构建的,从数据库中的几个表(调查、问题、答案等)中获取数据。此类的公共属性之一由一系列问题组成,存储为对象(也具有公共方法/属性等)。答案也一样。用于构建这些类的代码非常简单,并且不在此处讨论。
这是调查控制器中的代码。我复制/粘贴和编辑/删除了几行以使其更清晰:
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 调查表单类仅在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,
));
}
向表单元素添加过滤器、验证器和装饰器现在很简单。我的建议有点脏,但我认为它可以完成工作。如果我发现更优雅的东西,我会添加一个新的提案。随意发布不同的答案/解决方案。