Laravel Facades to Constructor Injection: Replace Facade Aliases with Full Classes in 2 hours

April 2022 update

Since Rector 0.12 a new RectorConfig is available with simpler and easier to use config methods.

Laravel facades are known as static service locators. The idea is get any service anywhere, which comes very handy for project bootstrapping.

Around Laravel 6, released in March 2019, the Laravel community started moving away from facades towards clearly typed constructor injection.

Today we'll take 1st step to make it happen.

It was a big surprise for us that it's not only external critics of Laravel but also from inside the community itself. There is a proposal to remove facades completely in Laravel 6:

Laravel facades usage count

But as we well know, programmers are lazy:

"Give me the tools to solve my problem, and I'll consider it.
Give me an extra work, and I'll pass."

So, in the end, the discussion was closed, and nothing has changed. Yet, the spark that started a fire...

Removing Laravel class aliases

What the... Alias?

Aliases are defined in config/app.php under alias key. They're basically converted to:

// 'original class', 'alias'
class_alias('Some\LongerClass\App', 'App');

That means these 2 lines are identical:

App::run();
Some\LongerClass\App::run();

2 ways to do 1 thing is a code smell. It's also the low handing fruit we can make colossal leap to make our code base less magical.

As a bonus, we'll save few in config/app.php:

Dropping Laravel facade aliases

3 Steps to Remove Facade Aliases

Class alias is basically inverted class rename. So all we need to do si rename short classes (App) to long ones (Some\LongerClass\App), e.g.:

Laravel facades replaced by fully qualified class names
  1. Install Rector
composer require rector/rector --dev

# creates "rector.php"
vendor/bin/rector init
  1. Configure rector.php

Look how Laravel is helping us here. Just copy paste lines from config/app.php → aliases:

use Rector\Renaming\Rector\Name\RenameClassRector;
use Rector\Config\RectorConfig;

return function (RectorConfig $rectorConfig): void {
    $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [
        'App' => 'Illuminate\Support\Facades\App',
        'Artisan' => 'Illuminate\Support\Facades\Artisan',
        'Auth' => 'Illuminate\Support\Facades\Auth',
        'Blade' => 'Illuminate\Support\Facades\Blade',
        'Broadcast' => 'Illuminate\Support\Facades\Broadcast',
        'Bus' => 'Illuminate\Support\Facades\Bus',
        'Cache' => 'Illuminate\Support\Facades\Cache',
        'Config' => 'Illuminate\Support\Facades\Config',
        // ...
    ]);
};
  1. Run Rector
vendor/bin/rector process src

That's it!


Blade Templates?

What are Blade templates in simple words? PHP files with syntax sugar.

Most Rector rules or static analysis would fail here, but Rector can rename classes even in non-standard PHP files like Blade, TWIG, Latte, Neon, or YAML. We rarely want to rename a class in PHP code and keep the old name in configs and templates.

Laravel facade aliases in Blade templates

Blade templates are covered too!


Real Case Study with Eonx

You're probably thinking: "Demo always looks nice. It's designed to look nice. But what about a real private project?" We're glad you doubt.

Recently, we applied this refactoring on a project of size 250 000-750 000 lines of code, in cooperation with Australian company, Eonx.

Here are all the pull-requests, we had to make:

Two days of manual work replaced by Rector

The biggest pull-request has changed 45 600 lines.


The Numbers

  • we changed ~65 000 lines of code
  • it took ~15 hours of Rector configuration work and research (= the insights in this post)
  • and 4 hours of coding work and running Rector

Now the same work on the same project would take 2 hours in total. And we believe you can do it for your project too!


Happy refactoring!