Dependency Injection with inherited Controllers in Laravel 5
Usually, when setting up my controllers in a Laravel 5 application, I end up creating one or several base controllers for different entry points (e.g. APIController, FrontendController, …) While I deem this a good practice, it can lead to problems with Laravel’s otherwise fantastic Dependency Injection. To illustrate, take a look at the following:
|
|
As some IDEs and testing tools would say: There are multiple problems!
- The
BlogController
’s constructor does not call the parent. - The constructors do neither match nor can all required parameters be handed down.
- Actually there is no number three but lists with two points always seem awkward.
Look at the mess I made!
Not calling the parent constructor which probably does important things? Bad idea. Could be fixed with changing the constructor of BlogController
to:
|
|
But then again that’s not quite right too, is it? It should be more along the lines of this:
|
|
Which is ugly as hell. Let alone remembering that for all of the other descendants of the FrontendController
.
Let’s make that pretty
Right around the time I realized that I didn’t want to write that second version even once, I thought “hey, Eloquent models have this boot() method. That could be a way to go.”
Said and done. I refactored my code to this:
|
|
Which, of course, did not work. And - as too often is the case - the error was all too obvious to me once I had committed the crime. So, after a while, I figured that if Laravel can resolve class names to inject from type hints, why shouldn’t I. Thus followed some research on method reflection and I ended up with this:
|
|
And this, finally, works just as expected. One thing to note though: Bad things will happen if you have anything but type-hinted to-be-resolved classes as attributes to the boot()
method.