Reputation: 1972
I have various Loggers defined in my module_config. Each controller or service that needs a specific logger needs to get the logger via its factory injected.
Ideally I don't want to worry about this injection and can make the loggers gloablly accessable (without having the service locator in my service/controller). They should be lazy loaded/instanciated, only when I need them.
Is there a way to do so? I was thinking of initializers, treats or using the event manager.
I know, It sounds like having the service locator back.
Any ideas?
Upvotes: 0
Views: 69
Reputation: 76
I guess the cleanest way is to use a controller plugin to call upon your loggers from a controller.
Implementation is pretty simple:
Create a new PHP class and have it extend Zend\Mvc\Controller\Plugin\AbstractPlugin
.
It's constructor should accept the logger(s) as a dependency, and it's __invoke method can be used to "magically" retrieve a logger.
Next, create a factory for it, implementing Zend\ServiceManager\FactoryInterface
and use it to inject the dependencies (i.e., the loggers)
Register the factory in your servicemanager configuration:
'controller_plugins' => array(
'factories' => array(
'Logger' => 'MyApp\Controller\Plugin\Logger',
)
),
You are then able to call it in a controller like so:
$this->logger();
(See http://lab.empirio.no/custom-controller-plugin-in-zf2.html) for more information on creating custom controller plugins.
Lazy-loading loggers can be handled by registering them as lazy services under the lazy_services
key in your service_manager
configuration.
As for your services, you can implement your own version of a ServiceLocator
(also known as a plugin manager).
It would work a lot like the ViewHelperManager
, ControllerPluginManager
, ValidatorPluginManager
, etc.
I won't explain how to do that as it's a lot of code and many how-to's exist on the web on how to create one.
EDIT: As @tasmaniski noted below you could use injection based on marker interfaces using initializers (ZF2 uses this internally through the 'Aware' interfaces). Do note that initializers are relatively slow especially when used incorrectly, i.e. as a closure in your Module.php or module.config.php file.
Also, initializers get called upon for each service fetched by the ServiceManager
's get()
mtehod and can thus add significant overhead.
It is however a much easier and faster solution than writing your own implementation of a plugin manager.
Upvotes: 1
Reputation: 4898
I have exactly the same question in my application/architecture. So the solution was:
In the scope of Controllers, as @FuST said you have to create controller plugin. Than the logger will be available across all controllers.
In the scope of services, I you can do a "Interface Injection". So in your Service you have to add 3 thing:
// #1 Create interface with setLogger($logger); method
class YourService implement LoggerInterface {
private $logger; // #2 Define private $logger;
// #3 Add method that you will use to inject the $logger later
public function setLogger($logger){
$this->logger = $logger;
}
}
Than create initializer and inject $logger in every class that implement the LoggerInterface.
Upvotes: 0