我正在创建ZF2民意调查模块。我有许多问题的民意调查。每个问题的答案都可以是多个答案或单个答案(Radio或MultiCheckbox)。如何创建一个我可以向前端显示的动态表单?
这是我尝试过的,但表单没有正确验证...
模块\投票\ SRC \投票\表格\ PollFillingQuestionsForm.php
<?php
namespace Polls\Form;
use Zend\Form\Form;
use Polls\Form\Fieldset\PollFillingQuestionAnswerFieldset;
use Polls\Form\Fieldset\PollFillingQuestionFieldset;
class PollFillingQuestionsForm extends Form {
public function __construct($questionsObject) {
parent::__construct('questionsForm');
$questionsFieldset = new PollFillingQuestionFieldset('questions');
//$questionsObject is array of question objects.
foreach ($questionsObject as $questionObject) {
$fieldset = new PollFillingQuestionAnswerFieldset($questionObject->id, array(), $questionObject);
$questionsFieldset->add($fieldset);
}
$this->add($questionsFieldset);
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Submit Poll',
'class' => 'btn btn-success',
),
));
}
}
模块\投票\ SRC \投票\表格\字段集\ PollFillingQuestionAnswerFieldset.php
<?php
namespace Polls\Form\Fieldset;
use Polls\Model\QuestionAnswer;
use Zend\Form\Fieldset;
use Zend\Stdlib\Hydrator\ArraySerializable;
class PollFillingQuestionAnswerFieldset extends Fieldset {
public function __construct($name, $options, $questionObject) {
parent::__construct($name, $options);
$question = $questionObject;
$this->setLabel($question->title);
$type = 'Radio';
$elementType = 'radio';
switch ($question->answer_type) {
case 'many':
$type = 'MultiCheckbox';
$elementType = 'checkbox';
break;
case 'one':
$type = 'Radio';
$elementType = 'radio';
break;
default:
$type = 'Radio';
$elementType = 'radio';
break;
}
$this->setHydrator(new ArraySerializable())
->setObject(new QuestionAnswer());
$answers = $question->getAnswers();
$answerValues = array();
foreach ($answers as $answer) {
$answerValues[$answer->id] = $answer->title;
}
$this->add(array(
'name' => 'answer',
'type' => $type,
'options' => array(
'type' => $elementType,
'value_options' => $answerValues,
),
));
}
}
答案 0 :(得分:1)
我以前做过这个,使用干净的Factory策略,您可以将依赖项注入表单和输入过滤器。神奇之处在于你的工厂。
首先在服务管理器配置中连接:
'form_elements' => [
'factories' => [
DynamicForm::class => DynamicFormFactory::class,
],
],
'input_filters' => [
'factories' => [
DynamicInputFilter::class => DynamicInputFilterFactory::class,
],
],
首要任务是让你的FormFactory正确完成。
class DynamicFormFactory implements FactoryInterface, MutableCreationOptionsInterface
{
/**
* @var array
*/
protected $options;
/**
* Set creation options
*
* @param array $options
* @return void
*/
public function setCreationOptions( array $options )
{
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
/**
* @var \Zend\Form\FormElementManager $serviceLocator
* @var \Zend\ServiceManager\ServiceManager $serviceManager
*/
$serviceManager = $serviceLocator->getServiceLocator();
try
{
$options = /* set up your form's config, you have the service manager here */;
$form = new DynamicForm( $options );
$form->setInputFilter( $serviceManager->get('InputFilterManager')->get( DynamicFormFilter::class, $options ) );
}
catch( \Exception $x )
{
die( $x->getMessage() );
}
return $form;
}
}
然后,通过MutableCreationOptionsInterface实现对DynamicInputFilterFactory中的$options
做出反应。您通常不希望表单和过滤器具有“选项感知”,让工厂负责处理。
class DynamicInputFilterFactory implements FactoryInterface, MutableCreationOptionsInterface
{
protected $options;
/**
* Set creation options
*
* @param array $options
* @return void
*/
public function setCreationOptions( array $options )
{
$this->options = $options;
}
public function createService( ServiceLocatorInterface $serviceLocator )
{
/* do stuff with $this->options */
return new DynamicInputFilter(
/* pass your transformed options */
);
}
}
接下来,您所要做的就是根据MutableOptions传递给他们的内容创建表单和输入过滤器。在__construct
中设置依赖项(不要忘记调用parent :: __ construct)并根据传入的选项在init
中初始化表单。
我怀疑你在ZF2中有一个很好的基础,所以我会在这里停下来。这应该让你在路上。外卖是MutableCreationOptionsInterface并将您的InputFilter和Form构造分开,将两者结合在Form Factory中。