I've been doing a lot of reading on dependency injection over the last few days and have been using Aura.DI to have a play with IoC principles. I've come up against a few issues I've heard are common when implementing this pattern, but I'm still not quite sure on some of the details.
If I want to inject a logger (say Monolog) into a controller class (just an easy example), I would like to use the class name as the logging channel (basically new Logger('somecontroller')), as far as I can tell, this would mean manually defining that 'injection' for each and every class, am I right in thinking this?
This:
$controller = new PageController(new Logger('PageController'));
in Aura.DI, would be:
$di->params['PageController'] = [
'logger' => $di->lazyNew('Logger', ['name' => 'PageController'])
];
but I'd have to do that for every controller that I want a different logging channel for?! I've heard that you can use the Abstract Factory Pattern here, but I'm not sure how this would work? (I understand the Factory pattern, but have never been in a situation where I thought it would help me. The Abstract Factory pattern is new to me though)
I know I could write a simple method to iterate over an array of controllers and do this in a less verbose way, but it does feel kind of wrong to have to do that.
I also came across this post on reddit and thought it made a bit of sense. If I'm going to have to manually configure all of these dependencies anyway, why not just make my configuration the actual implementation? Maybe this falls apart when the dependency tree gets a bit larger? I thought it was worth asking what peoples' opinions were though.
EDIT: Just mocked up an example of how the DIY approach could work and it seems pretty alright actually... thoughts? (probably should have made a lot of those methods private, but you get the picture).
Any light that you can shed on any/all of my questions would be appreciated.
You could do this via a few different ways.
Inject a
LoggerFactoryclass to thePageController.Using withName() of the same
Logger. May be this is easier one. You inject the logger and call$newlogger = $this->logger->withName(__CLASS__);and get the cloned new instance.Using the Instance Factories
Here
ExampleNeedsFactoryisPageController,ExampleStructisLoggerNote : In this case
getLoggeralways returns new logger. If you need same instance set the logger.You can also move these methods to an
AbstractControllerclass so you don't need to write everytime the what you need to inject to the controller. (@camel_case did mentioned about this in his comments)There is also auto resolution feature for Aura.Di which helps not to write lots of configuration.
Hope that helps!