Injecting dependencies into your ZF2 controllers
When starting working with Zend Framework 2, it’s common to copy the skeleton and put your controller definitions in module.config.php like this:
'controllers' => array( 'invokables' => array( 'Application\Controller\Index' => 'Application\Controller\IndexController', 'Application\Controller\Blog' => 'Application\Controller\BlogController', ), ),
The controllers keyword is picked up by the ControllerManager which is an instance of the ServiceManager which means that it creates the controller instance for you when the dispatcher needs it.
As it’s just a service manager, we configure it to inject the dependencies that the controller needs rather than having to go fishing for them later. The easiest way to do this is to add a callback to the Module class to do the work in.
To convert the Blog controller, we would remove the line from the invokables config array and then write a getControllerConfig() method that would looks something like this:
public function getControllerConfig() { return array( 'factories' => array( 'Application\Controller\Blog' => function ($sm) { $locator = $sm->getServiceLocator(); $blogMapper = $locator->get('Application\Mapper\BlogMapper'); $commentMapper = $locator->get('Application\Mapper\CommentMapper'); $controller = new BlogController($blogMapper, $commentMapper); return $controller; }, ), ); }
ZF2 controllers tend to extend AbstractActionController which does not define a constructor. This means that you can define your own constructor in your controllers and use it to inject the dependencies that your controller needs. In this example, our BlogController needs two database mappers, so we retrieve them from the service manager and then instantiate our BlogController object.
Nice and simple.
You somewhat beat me to the punch :D . I'm working on a post about using factory rather than invokables when creating services.
A factory class should work just as well as a callable, no?
Adrian,
Yes, a factory class works even better as you can configure it in module.config.php and so it can be cached by the ModuleManager.
I was wondering what the pros/cons are to inject an object via constructor if it's not going to be used in all actions. Isn't it going to introduce unnecessary overhead of creating an object?
It it's not used in all actions you should inject the dependencies aslazy services.
http://framework.zend.com/manual/2.3/en/modules/zend.service-manager.lazy-services.html
There's no cons ;)
Will be better when may be inject object in to Action.
Because, injecting an object via constructor if it’s not going to be used in all actions – violation of the principle SRP