Reputation: 39364
There are at least three methods -- Zend\Di, ConfigAwareInterface, and ControllerFactory -- I've considered for injecting configuration into controllers.
The more or less official recommendation is the ControllerFactory, which leads to this code (or this code if you prefer closures -- I don't, as they're harder to test):
// module.config.php
'controllers' => array (
'factories' => array (
'Module\Concept\Index' => 'Concept\ControllerFactory\IndexControllerFactory',
),
),
'some_config_key' => array (
'x' => 'foo'
),
// src/Concept/ControllerFactory/IndexControllerFactory.php
class IndexControllerFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator) {
$config = $serviceLocator->getServiceLocator()->get('config');
$controller = new \Html\Controller\IndexController($config['some_config_key']);
return $controller;
}
}
// src/Concept/Controller/IndexController.php
class IndexController {
public function __construct($config) {
// here we go, yay! we have $config['x'] == 'foo'
}
}
If each action needs different configuration (eg, one might need DB, another might need paypal), it doesn't seem proper to pass all controller configuration when only some of it is needed for the action.
So, should the knowledge of which configuration is needed for which action go into the factory or into the controller? That is, should the factory give the controller only what it needs based on the action at hand, or should the controller be given all its configuration and internally figure it out?
Update
Action-specific dependencies are just that: specific. The controller declares what it needs then uses that in whatever ways are necessary. That two actions have radically different needs suggests that perhaps the controller has too broad a scope, and may be a candidate for separation.
But regardless, the best way -- the way that was clear, robust, and apparently in line with future direction of ZF -- is to manufacture the needed services in a service factory, then manufacture a controller with the requisite services.
Two factories: service and controller. The controller declares its __construct
contract with the services it must have, then the factories manufacture those as needed from the module config.
Upvotes: 2
Views: 364
Reputation: 10947
This question is mostly opinion-based, so you can get many diferent answers.
The two approaches are good, since:
So probably the best approach is to inject only the configuration that it is expecting. Actually, that is what we use to do when creating a ViewHelper, where ususally we dont inject everything but only what we need.
This could be confusing, since sometimes you could need some other general config also, and not only the config purely related to the module, and in that cases you will have to think about it. But in most cases, the more elegant solution probably will be to inject just what you need.
As a further and important argument, i read in sam minds blog that
...there are still a couple of things that are just not ideal. A little example would be that a lot of people use $this->getServiceLocator() inside their Controllers. While this is OK, it’s actually considered bad practice. The way things are looking right now, this feature will be removed in Zend Framework 3 (ZF3) to basically force people to use proper dependency injection using the ServiceManager.
so we can think is that the proper approach is to bring the dependency injection as far as we can and let every component know as little as we can.
Upvotes: 1