Another cool feature shipped with the release of Laravel 5.4 is the ability to use Facades on the fly.

Automatic Facades with the HighOrders Collections are my most favorite features of this release!

I won’t explain what Facades are because the official documentation is quite informative. So I assume you are familiar with them.

How To Create Custom Facades

Before explaining the new feature lets see how you can define a custom facade.

As an example I borrow the class used by Taylor Otwell:

namespace App; class Zonda

{

public function zurf()

{

return 'Zurfing';

}

}

Given this class we need to define the custom Facade like that:

namespace App\Facades; use Illuminate\Support\Facades\Facade; class FacadeName extends Facade

{

protected static function getFacadeAccessor()

{

return App\Zonda::class;

}

}

The last step is to register the Facade into config/app.php:

'aliases' => [

// ...

'Zonda' => App\Facades\FacadeName::class

]

The idea behind this new feature is to automate this flow for defining facades inline:

use Facades\{

App\Zonda

}; Route::get('/', function () {

return Zonda::zurf();

});

Using the common namespace Facades\.

Behind The Scenes

Each time we use a grouped import that starts with the Facades namespace a new facade is generated on the fly. It works also with a single line import.

The Illuminate\Foundation\AliasLoader handles this behavior. It registers a custom autoload function when the framework bootstraps.



* Register the loader on the auto-loader stack.

*

* @return void

*/

public function register()

{

if (! $this->registered) {

$this->prependToLoaderStack();



$this->registered = true;

}

}



/**

* Prepend the load method to the auto-loader stack.

*

* @return void

*/

protected function prependToLoaderStack()

{

spl_autoload_register([$this, 'load'], true, true);

} /*** Register the loader on the auto-loader stack.void*/register()(!->registered)->prependToLoaderStack()->registered = true/*** Prepend the load method to the auto-loader stack.void*/prependToLoaderStack(), 'load', true, true

When the framework bootstraps it calls the register method and prepend to the loader stack the load method.

/**

* Load a class alias if it is registered.

*

* @param string $alias

* @return bool|null

*/

public function load($alias)

{

if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {

$this->loadFacade($alias);



return true;

}



if (isset($this->aliases[$alias])) {

return class_alias($this->aliases[$alias], $alias);

}

}

If the $alias starts with the $facadeNamespace (default is Facade) then it loads the custom facade on the fly using the loadFacade method.

/**

* Load a real-time facade for the given alias.

*

* @param string $alias

* @return bool

*/

protected function loadFacade($alias)

{

tap($this->ensureFacadeExists($alias), function ($path) {

require $path;

});

}

After it ensures that the facade exists it requires the real time generated facades into the namespace.

The ensureFacadeExists method is what makes the magic real.

/**

* Ensure that the given alias has an existing real-time facade class.

*

* @param string $class

* @return string

*/

protected function ensureFacadeExists($alias)

{

if (file_exists($path = base_path('bootstrap/cache/facade-'.sha1($alias).'.php'))) {

return $path;

}



file_put_contents($path, $this->formatFacadeStub(

$alias, file_get_contents(__DIR__.'/stubs/facade.stub')

));



return $path;

}

To check if the facade exists the first thing that it does is to see if the facade already exists. As you can see cached facades are generated using the sha1 hash function of the alias name. If the facade is cached it returns the path of the file.

Otherwise, it generates on the fly the facade using this stub.

<?php



namespace DummyNamespace;



use Illuminate\Support\Facades\Facade;



/**

* @see \DummyTarget

*/

class DummyClass extends Facade

{

/**

* Get the registered name of the component.

*

* @return string

*/

protected static function getFacadeAccessor()

{

return 'DummyTarget';

}

}

As you can see it’s like what we used before to create them manually. I let you see alone what the formatFacadeStub does.

The rest of the load method works as before so I let you figure out the rest also in this case :D

This is what was added to make put in place this feature.

My suggestion is to start using automatic facades whenever is possible, their impact is negligible. To see when to use facades in general a good read is available in the official documentation.