Search code examples
phpzend-framework2

Form creation using factory for fieldset – how to connect the two?


I want to create a form in Zend Framework 2 utilizing a fieldset created by a factory, but I am having problems to connect the fieldset with the form.

The fieldset is created like this:

<?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',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ));
    }
}

The form:

<?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',
        ));
    }
}

And the controller that should connect the two:

<?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
        ));
    }
}

Depending on what I try, the results vary between an empty view or exceptions.

For example, with the code posted above, I get Plugin of type FormElements\Form\PersonalDataFieldset is invalid; must implement Zend\Form\ElementInterface.
Of course I could implement the Interface because the exceptions tells me to do so, but I would like to understand what I am doing, but I don't know why this interface should be required?

  • Where am I going wrong – why does the way I try it does not work?
  • When creating a Fieldset, the the factory's method createForm is used, but there is also createFieldset– what is the correct method? Also, why is there no need to extend Zend\Form\Fieldset?

Solution

  • I would avoid calling $form = new PersonalDataForm(); in your controller.

    I would inject that dependency in a factory, that factory should have access to the "FormElementManager"

    FormElementManager is a AbstractPluginManager where one can store all their form related services, including Elements, Fieldsets and full Forms (as they all extend Zend\Form\Element)

    By calling your form services from the plugin manager (and making sure to inject that plugin manager into any subsequent form factories), you won't run into these "Invalid Plugin" errors.

    The "Invalid Plugin" exception usually means one of two things. You didn't register your element with the plugin manager, or you didn't properly inject the plugin manager where you need it.