I am creating a MVC-ish framework in PHP. I am trying to implement a DI Container to allow the creation of controller objects (among others).
My MVC framework is pretty typical. Each module (or component if you wish) has a controller responsible for executing requests. These module controllers typically extend a base Controller
class. All controllers will accept Request
and Response
objects as arguments.
The confusion occurs because some controllers may need different arguments in order to function. For example: Many controllers will need a Database
object; Controllers which send mail may need a Mailer
object; while a controller which logs data may need a Log
object. The DI Container will contain the recipes for creating all these controllers.
My front controller needs to be able create any of these controller objects, as specified by a request. Furthermore, each controller needs to be able to create any other controller.
How do I get my front controller and module controllers to access the DI Container in a way that doesn’t result in a dependency on the DI Container by each controller?
I actually don’t mind if the front controller is dependent on the container, I am more concerned about the module controllers.
Thanks,
You’re going to have to have that dependency on the DI container somewhere. If it’s the front controller, fine, but make sure that the front controller is then the single point of origin for all other controllers. All controllers should be created here.
Your DI Container should be clever enough to resolve dependencies to an unlimited depth. Any dependency a controller might have will get resolved by the container and injected into the controller. If any of those objects also have dependencies they should also get resolved by the container.
In my opinion, this is a good approach for several reasons. It gives you a way of removing calls to service locators or factories. In any class that uses the framework, you’ll just need to worry about what that class is doing, and you can safely assume that everything it need will be provided. The other benefit is that you can share stuff across components. Your controller and a different component can reuse the same instance of a db repository or something like that. And of course, there’s the testability that DI brings.
2