How to turn Laravel from Static to Dependency Injection in one Day

3 min

Mon, Mar 4, 2019

X comments

Edit Post

A framework is just a tool. Each teaches you coding habits you need to use them effectively. Like Laravel gives you speed at prototyping with static "facades". But the applications grows, so does the team, so does your skill and you start to prefer constructor injection.



What then? Switch framework or rewrite? But what if all you need is to switch single pattern?

I don't use Laravel in my own life, but I follow the community closely. It likes the idea of Contracts from day 1 and it's also part of Rector upgrade set.

Recently I read the Moving away from magic — or: why I don’t want to use Laravel anymore on medium by Niklas Schöllhorn.

Read the post, it's really beautifully written with respect to the framework by somebody, who uses is for 2 years. Also, I think it's about the natural evolution of code and how to deal with it, not Laravel itself.

Niklas finishes the post with a reasonable statement:

Other frameworks and tools come with better-designed defaults and less magic. So for now, I’ll say goodbye to Laravel.

But is switching the framework (language, girlfriends, parents...) really the best solution?

Do You Leave Your Kid on Puberty?

Thing is, every framework (and developer) has this step in evolution. So did Symplify with static methods.

Each framework I used in some period of its evolution used static:

Nette

<?php $result = Container::get('some_service')->someMethod();

Symfony

<?php $result = $this->get('some_service')->someMethod();

Laravel

<?php $result = SomeService::someMethod();

Help Your Parents Grow

I don't think the point is to leave the framework but to help it to the quality. E.g. Symfony constructor injection autowiring as we know it today wasn't always there. It was first suggested around Symfony 2.3 but strictly rejected by Fabien as an anti-pattern.

It took many bundles like Kutny\AutowiringBundle, Skrz\Autowiring or Symplify\Autowiring, closed issues and PRs with proof of concept before the Symfony core team was convinced enough to accept next autowiring-PR, that laid the foundation to autowiring we use today.

This is a completely normal process of community learning.

"So How do I get rid of Static in Laravel?"

One option is change pattern by switching to another framework, that already promotes the feature you want. I did this once with Nette when the development stopped around 2015. First, I tried to add a feature, make packages with integration and propose PRs and issues. But after a few years of failure, I decided to switch to Symfony.

The second option is to try the approach in your framework, regardless of what is considered best practice or the framework-way.

How move to Dependency Injection in Laravel?

I like the way suggested in post above.

<?php namespace App\Http; use App\Example; use Request; use Response; class ExampleController extends Controller { + /** + * @var ResponseFactory + */ + private $responseFactory; + + public function __construct(ResponseFactory $responseFactory) + { + $this->responseFactory = $responseFactory; + } + public function store() { $example = 5; - return Response::view('example', + return $this->responseFactory->view('example', ['new_example' => $example] ); } }

That looks great! If you have ~10 cases like that, you're done instead of reading this post.

But what if your project is commercially successful and there are 100+ cases like this? You'd probably think "it would be nice for my small pet project, but my boss wouldn't pay for that".

Rector to the Rescue

These kinds of problems are so 2018. Recently Rector got on board Laravel instant upgrades, first with Laravel 5.8.

Next impulse was the post by Niklas, so I've converted his idea to Rector rule. The change from facades to constructor injection can be done with new laravel-static-to-injection :

vendor/bin/rector process /src --set laravel-static-to-injection

No need to switch framework and you can enjoy new constructor injection in your Laravel application matter of minutes.

Happy coding!