Dependency Injection in Zend Framework 2

640 Views Asked by At

Actually, in my ZF2 project I've created base classes for models, forms and so on. For example: I noticed that I would probably need ServiceLocator in my models, so I created a class Application\Model\Base that implements the ServiceLocatorAwareInterface. This also applies to my forms.

I was thinking if that was the best way to do this or if I should pass the dependencies in the constructor. So I came with a problem today:

I have a form (Application\Form\Customer\Add) that needs to use the ServiceLocator in its constructor. But in this point, the ServiceLocator has not been set yet (the constructor is called before setServiceLocator()).

So, what do you think is the best way to solve this? Should I pass the dependencies by the constructor or continue using this approach that I'm actually using (and try to solve the customer form problem another way)?

1

There are 1 best solutions below

0
On

I think, it is better to create factory for your form and inject only needed dependencies from service locator and not a whole service locator.

Example of this factory with hydrator:

namespace Application\Form;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class AddFormFactory implements FactoryInterface
{
    /**
     * @param ServiceLocatorInterface $serviceLocator
     * @return AddForm
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        // assumes hydrator is already registered in service locator
        $form = new AddForm(
            $serviceLocator->get('MyAddFormHydrator')
        );

        return $form;
    }
}

Example of your AddForm:

namespace Application\Form;

use Zend\Form\Form;
use Zend\Stdlib\Hydrator\HydratorInterface;

class AddForm extends Form
{
    public function __construct(HydratorInterface $hydrator, $name = null, $options = [])
    {
        parent::__construct($name, $options);

        // your custom logic here
    }
}

And finally, you have to add this to your service manager configuration:

'service_manager'  => [
    'factories' => [
        'Application\Form\AddForm' => 'Application\Form\AddFormFactory',
    ],
],