使用Zend Framework 2动态生成表单

时间:2015-07-06 09:03:57

标签: zend-framework2 zend-form

我正在创建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,
        ),
    ));
}
}

1 个答案:

答案 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中。