3

I create custom element like here: ZF2Docs: Advanced use of Forms

1.Create CustomElement class in Application/Form/Element/CustomElement.php

2.Add to my Module.php function

public function getFormElementConfig()
{
    return array(
        'invokables' => array(
            'custom' => 'Application\Form\Element\CustomElement',
        ),
    );
}

If I use FQCN it works fine:

$form->add(array(
    'type' => 'Application\Form\Element\CustomElement',
    'name' => 'myCustomElement'
));

But if I use short name:

$form->add(array(
    'type' => 'Custom',
    'name' => 'myCustomElement'
));

throws Exception:

Zend\ServiceManager\ServiceManager::get was unable to fetch or create 
an instance for Custom
Sam
  • 16,435
  • 6
  • 55
  • 89
Ildar
  • 798
  • 2
  • 14
  • 35
  • @AydinHassan How exactly does that relate like.. at all? :D @Ildar, just to make sure, the Elements class is called `CustomElement` and not `Custom`? – Sam Apr 09 '13 at 06:07
  • @Sam, yes, the Elements class is called CustomElement – Ildar Apr 09 '13 at 06:29
  • I have changed custom on customElement in invokables and it works. – Ildar Apr 09 '13 at 07:01

1 Answers1

4

Problem

The error is probably due to how you are instantiating the $form object. If you just use the new Zend\Form\Form expression or something similar the form will not be set up with the correct service locator.

$form = new \Zend\Form\Form;
$form->add(array(
    'type' => 'custom',
    'name' => 'foobar',
));

Solution

The trick here is to use the FormElementManager service locator to instantiate the form.

// inside a controller action
$form = $this->getServiceLocator()->get('FormElementManager')->get('Form');
$form->add(array(
    'type' => 'custom',
    'name' => 'foobar',
));

Better yet, define a form() method in your controller as a shortcut to do this for you:

class MyController extends AbstractActionController
{
    public function form($name, $options = array())
    {
        $forms = $this->getServiceLocator()->get('FormElementManager');
        return $forms->get($name, $options);
    }

    public function createAction()
    {
        $form = $this->form('SomeForm');
        // ...
    }
}

Explanation

Each form object is attached to a form factory which is in turn attached to a service locator. This service locator is in charge of fetching all the classes used to instantiate new form/element/fieldset objects.

If you instantiate a new form object (all by itself), a blank service locator is instantiated and used to fetch later classes within that form. But each subsequent object is then attached to that same service locator.

The problem here is that getFormElementConfig configures a very specific instance of this service locator. This is the FormElementManager service locator. Once it's configured, all forms pulled from this service locator will then be attached to this service locator and will be used to fetch other elements/fieldsets etc.

Hope this solves your issue.

radnan
  • 1,279
  • 10
  • 10
  • Thank you! First problem was that in invokables section was "custom" instead of "customElement". The second problem is how you said: did not set correct service locator. I create form in view using form factory. So, I call $factory->setFormElementManager($sm->get('FormElementManager')); in view – Ildar Apr 09 '13 at 07:14