使用工厂为fieldset创建表单 - 如何连接两者?

时间:2015-04-07 12:55:21

标签: php zend-framework2

我想利用工厂创建的字段集在Zend Framework 2中创建一个表单,但是我遇到了将字段集与表单连接的问题。

字段集的创建方式如下:

<?php    
// File: module/FormElements/src/Form/PersonalDataFieldset.php

namespace FormElements\Form;

use Zend\Form\Factory;

class PersonalDataFieldset extends Factory
{
    public function __construct()
    {
        $factory = new Factory();
        $form = $factory->createForm(array(
            'fieldsets' => array(
                array(
                    'spec' => array(
                        'name' => 'data',
                        'options' => array(
                            'label' => 'Fieldset Test',
                        ),
                        'elements' => array(
                            array(
                                'spec' => array(
                                    'name' => 'fname',
                                    'type' => 'text',
                                ),
                            ),
                            array(
                                'spec' => array(
                                    'name' => 'lname',
                                    'type' => 'text',
                                ),
                            ),
                            array(
                                'spec' => array(
                                    'name' => 'email',
                                    'type' => 'email',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ));
    }
}

表格:

<?php
// File: module/FormElements/src/Form/PersonalDataForm.php

namespace FormElements\Form;

use Zend\Form\Form;

class PersonalDataForm extends Form
{
    public function __construct()
    {
        parent::__construct();

        // Field not contained in the fieldset - this works
        $this->add(array(
            'name'=> 'some-name',
            'type' => 'text',
            'options' => array(
                'label' => 'Test Label',
            ),
        ));

        // Here I am trying to add the fieldset – this does not work
        $this->add(array(
            'name' => 'some-other-name',
            'type' => 'FormElements\Form\PersonalDataFieldset',
        ));
    }
}

应该连接两者的控制器:

<?php
// File: module/FormElements/src/Controller/FormElementsController.php

namespace FormElements\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

use FormElements\Form\PersonalDataForm;

class FormElementsController extends AbstractActionController
{
    public function indexAction()
    {
        $form = new PersonalDataForm();

        return new ViewModel(array(
            'form' => $form
        ));
    }
}

根据我的尝试,结果会因空视图或异常而异。

例如,根据上面发布的代码,我得到Plugin of type FormElements\Form\PersonalDataFieldset is invalid; must implement Zend\Form\ElementInterface 当然我可以实现接口,因为异常告诉我这样做,但我想了解我在做什么,但我不知道为什么需要这个接口?

  • 我哪里错了 - 为什么我尝试它的方式不起作用?
  • 创建Fieldset时,使用工厂的方法createForm,但也有createFieldset - 正确的方法是什么?另外,为什么不需要扩展Zend\Form\Fieldset

2 个答案:

答案 0 :(得分:2)

我会避免在你的控制器中调用$form = new PersonalDataForm();

我会在工厂中注入该依赖项,该工厂应该可以访问“FormElementManager”

FormElementManager是一个AbstractPluginManager,可以存储所有与表单相关的服务,包括元素,字段集和完整表单(因为它们都扩展了Zend \ Form \ Element)

通过从插件管理器调用表单服务(并确保将该插件管理器注入任何后续表单工厂),您将不会遇到这些“无效插件”错误。

“无效插件”异常通常意味着两件事之一。您没有使用插件管理器注册您的元素,或者您没有在需要的地方正确注入插件管理器。

答案 1 :(得分:1)

移动字段和字段集,将方法从__construct()添加到init()方法,然后使用FormElementManager获取表单。它的工作方式与此处所述的zf2 docs

相同

编辑1:我修复了链接,似乎#符号已经正确编码

编辑2:这是ZF2文档部分的引用:

  

...自定义元素的示例代码...

     

现在是第一个问题。

     

如果要通过扩展Zend \ Form \ Form来创建表单类,则不能在__construct中添加自定义元素 - 或者(正如我们在上一个使用自定义元素的FQCN的示例中所做的那样),而是在init()方法中:

namespace Application\Form;

use Zend\Form\Form;

class MyForm extends Form
{
    public function init()
    {
        $this->add(array(
            'name' => 'phone',
            'type' => 'Phone',
        ));
    }
 }
  

第二个问题是你不能直接实例化你的表单类,而是通过Zend \ Form \ FormElementManager获取它的实例:

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        $sl = $this->getServiceLocator();
        $form = $sl->get('FormElementManager')->get('\Application\Form\MyForm');
        return array('form' => $form);
    }
}
  

最大的好处是,如果它们不符合您的需要,您可以轻松覆盖任何内置的Zend Framework表单元素。例如,如果要创建自己的Email元素而不是标准的元素,则可以简单地创建元素并将其添加到表单元素config,其中键与要替换的元素相同   ...