使用 Zend Framework 2 动态生成的表单
Dynamic generated form with Zend Framework 2
我正在创建 ZF2 轮询模块。我有很多问题的投票。每个问题都有可以是多个答案或单个答案(单选或多选框)的答案。如何创建可以显示给前端的动态表单?
这是我试过的方法,但表单验证不正确...
module\Polls\src\Polls\Form\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',
),
));
}
}
module\Polls\src\Polls\Form\Fieldset\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,
),
));
}
}
我过去曾这样做过,使用干净的工厂策略,您可以将依赖项注入表单和输入过滤器。魔法在于您的工厂。
首先在您的服务管理器配置中连接一些东西:
'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
作出反应。您通常不希望表单和过滤器是 'option aware',让工厂来处理。
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 中。
我正在创建 ZF2 轮询模块。我有很多问题的投票。每个问题都有可以是多个答案或单个答案(单选或多选框)的答案。如何创建可以显示给前端的动态表单?
这是我试过的方法,但表单验证不正确...
module\Polls\src\Polls\Form\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',
),
));
}
}
module\Polls\src\Polls\Form\Fieldset\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,
),
));
}
}
我过去曾这样做过,使用干净的工厂策略,您可以将依赖项注入表单和输入过滤器。魔法在于您的工厂。
首先在您的服务管理器配置中连接一些东西:
'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
作出反应。您通常不希望表单和过滤器是 'option aware',让工厂来处理。
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 中。