I'm working on building a PHP framework that behaves according to MVC principles and utilizes dependency injection. I think I have the front-controller part down; there is a working router that instantiates a controller instance and calls the appropriate action based on the requested URI.
Next up is dependency injection. I want to implement a Container that resolves dependencies using reflection. In doing so, I think I'm running into a problem with my controllers.
There are a number of what I call "system dependencies" that need to be available to derived controller classes. I haven't actually created all these dependencies yet, but it seems sensible that controllers have access to services like an InputProvider (to encapsulate get/post params or command line arguments), and maybe an Output dependency. Ideally, I'd use the framework's Container to inject these dependencies into the constructor of the controller - but this is where I run into problems.
If I use constructor injection for system dependencies in the controller, then I'm forcing derived controllers to manage the base controller's dependencies if they implement a constructor of themselves. That doesn't seem to be the most user-friendly. The other option is to use setter injection for system dependencies, but then derived controllers won't have access to these system dependencies if they should have need of them in their constructor.
The only solution I see that offers the best of both worlds is to make my controllers singletons. They'd have a private constructor so I can safely use setter injection without worrying about the constructors of derived classes. Instead, there would be an overridable initialize() method (assuming I get method injection working somehow), that basically fulfills the role of constructor (as in, an initializer for the derived controller). This way, constructor injection is replaced by method injection in the initialize() method, where all system dependencies would be available, without requiring the derived controller to manage them.
But then, a quick google search seems to unanimously say that singleton controllers are bad practice. I'm very unsure on how to proceed. I am probably overengineering this, but apart from wanting my application to be future-proof and maintainable, I also see it as a little exercise in applying best practices, so I'd like to do things "properly".
I think the best practice in this case would be to pass the responsibility of managing the required system dependencies to the derived controller. A dependency should probably only be instantiated if the derived controller actually has need of it. Why inject an InputProvider in the base controller if it is possible that a derived controller is never even going to use it? But at the same time, I keep coming back to user friendliness, and how nice it is to simply always have a $this->input
member available, such as in a framework like CodeIgniter.
I highly appreciate any and all contributions to my dillemas. I also apologise for the wall of text, but I couldn't think of any code examples that would make the job of explaining any easier, since it's all so abstract to me right now!
Sincerely,
A severely torn individual