Real-Time Facades in Laravel

Posted on

Real-time facades is a feature introduced in Laravel 5.4. It is a simple way to create Laravel facades quickly, without needing to write the actual facade class, by prefixing the namespace of the class we want to resolve out of container with Facades\.

Since it became available, I've used this feature and liked using it. It wasn't until recently that I decided to figure out how this, seemingly magical, thing works. How does one usually understand how things work in software development? I looked at the code.

Autoloading basics

When we try to use a class that is not available in the current scope, PHP runs registered autoload functions and maybe one will be able to load that class. Usually, autoload function registered by Composer is used and by default classes starting with App\ are located in the app/ folder, and the namespace matches directory structure.

So what happens when we prefix fully qualified class name with "Facades\"?

During framework bootstrapping, one of bootstrappers Illuminate\Foundation\Bootstrap\RegisterFacades, runs register() method on Illuminate\Foundation\AliasLoader singleton. This registers another autoload function and declares it should be run before previously registered autoloaders. This loader checks if the requested class starts with the prefix (Facades\ by default), otherwise it doesn't return anything, which means other loaders should be used if present.

If the class name begins with the prefix, first there is a check if the facade class has already been generated and cached for later use. If it is the first time the facade is needed, it needs to be generated and cached. This is done by getting the contents of a stub, replacing placeholders for the namespace with the prefix, facade class name, and target class. The path of the cached file is used to require it.

That's it, this "magical" thing wasn't complex at all!

Excercise in simplification

I believe that in order to better understand a concept or a part of a complex system, we should extract it from the whole and make something simple. So I extracted the essential components, with minimal implementation for getting an instance of the class we want resolved through the facade (instead of using a container, simple instantiation is used), into a simple example repository available on GitHub.