How to have a service manager in Form ?

EDIT 9 november 2012 : there will be soon a better solution for such a problem starting from Zend Framework 2.1. You can learn more in my another blog post here.

Sometimes, you will need to have the instance of the service manager in your Forms classes, for example the Doctrine 2′s entity manager, or retrieving fieldsets that need specific dependencies.

A simple solution to this problem is to create a class that extends Zend\Form\Form and implements ServiceManagerAwareInterface. Then, the setServiceManager will call a function called init, where you will create your forms, while being able to retrieve the service manager.

Here is such a class :

And for example a Register form :

 

10 réflexions au sujet de « How to have a service manager in Form ? »

  1. Evan Coury

    Thanks for this post. We ran into this issue when building a form containing a select box, whose options needed to be dynamically populated by a call to a service. If the form has a hard dependency on a service or object, I personally prefer not to make it aware of a service locator, but rather declare the dependency explicitly as a constructor parameter. You can then have a simple factory for your form, such as this:

    ‘my_form’ => function($sm) {
    $productService = $sm->get(‘product_service’);
    return new Form\Product($productService);
    }

    This way, there’s no hidden dependencies within the form due to the form internally pulling things with $sm->get(). You can easily tell exactly what is required for the form to operate properly.

    However, when pulling your form from the service manager, this does require you create a factory that instantiates the form with he requried dependencies. Your method may appeal to a RAD methodology, as no factories would be required — the form could function as a simple invokable due to automatically calling init() when the service manager is injected by the initializer.

    Répondre
    1. admin Auteur de l’article

      This is the good idea. The only (minor) problem is that if this is not the main form that needs it BUT a fieldset (contained in the form), we cannot use the factory to create fieldset (as we must give it the service manager as a parameter).

      I’ll try to code this solution and update my blog post.

      Répondre
        1. admin Auteur de l’article

          Hi,

          I didn’t find an acceptable solution. Therefore I switched back to created a Registry (yes, with static functions) to be able to retrieve the entity manager in my forms. Even if this is not a recommended practice, I believe in some cases it can be the simplest/cleanest solution. In this case, it is.

          Répondre
          1. booradleys

            Or maybe such like this into myform:
            $fieldset = new MyFielset();
            $fieldset->setServiceManager($this->getServiceManager);
            ?

  2. Chris O'Connell

    Hey thanks for the post! Have a question. I don’t see how the setServiceManager method gets called. Does it happen automatically just by implementing ServiceManagerAwareInterface or would we have to write some more code somewhere to call it first?

    Thanks

    Répondre
    1. admin Auteur de l’article

      Ha, yeah. It’s not that “magical”. You have to pull the form from the ServiceManager. And the ServiceManager, when creating the form object, will automatically “inject” the ServiceManager to every class that implements ServiceManagerAwareInterface.

      Basically, you have to add an entry in invokables array of the SM :

      ‘invokables’ => array(
      ‘my.form’ => ‘Common\Form\Form’
      )

      and then pull it in your code :

      $form = $serviceManager->get(‘my.form’);

      and your form will contain the service manager.

      Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">