Laravel Facades Part Three: Creating Custom Facades

November 21, 2016 —John Koster

This article is part of a four part series all about Laravel facades. Each of the parts are listed below:

It may become necessary when developing certain applications, or when creating packages to write a facade class. Creating a facade class is fairly simple. The first thing that is required is some actual concrete class the facade will be accessing. For this example, the following class will be used:

1<?php
2 
3class Calculator {
4 
5 /**
6 * Adds two numbers.
7 
8 * @param mixed $firstNumber
9 * @param mixed $secondNumber
10 * @return mixed
11 */
12 public function add($firstNumber, $secondNumber)
13 {
14 return $firstNumber + $secondNumber;
15 }
16 
17 // Possibly many more methods.
18 
19}

The next thing that needs to happen is the class needs to be registered with the service container:

1<?php
2 
3App::singleton('math', function()
4{
5 return new Calculator;
6});

Components are typically registered with the service container through the use of Service Providers.

The Calculator class instance was bound as a singleton because there does not need to possibly hundreds of instances of Calculator created: many consumers of the class can share a single instance (note that not all classes should be bound as a singleton). The important part is that we have an service container binding: math which will resolve to an instance of Calculator.

It is at this point a facade can be created. A facade is created by creating a new class and extending Laravel's abstract Facade class:

1<?php
2 
3use Illuminate\Support\Facades\Facade;
4 
5class Math extends Facade {
6 
7 /**
8 * Get the registered name of the component.
9 *
10 * @return string
11 */
12 protected static function getFacadeAccessor() { return 'math'; }
13 
14}

It is important to note that the value returned by the getFacadeAccessor() function matches the name of the service container binding: math. The facade will use that value to request a class instance from the service container and redirect method calls to that instance.

We will now examine how we would have used the Calculator class without the facade:

1<?php namespace App\Http\Controllers;
2 
3use Calculator;
4 
5class TestController extends Controller {
6 
7 public function getIndex()
8 {
9 // We will create an instance, instead of having it supplied
10 // through the constructor.
11 $calculator = new Calculator;
12 
13 $result = $calculator->add(1, 2);
14 }
15 
16}

now using the facade:

1<?php namespace App\Http\Controllers;
2 
3use Math;
4 
5class TestController extends Controller {
6 
7 public function getindex()
8 {
9 $result = Math::add(1, 2);
10 }
11 
12}

#Creating a Facade Alias

Creating a facade alias is completely optional. Package developers often include the following steps in their package installation instructions, but it is not required for a facade to work.

In the config/app.php file, there is an aliases configuration entry. By default it will look like this:

1<?php
2 
3// Other configuration items.
4 
5'aliases' => [
6 
7 'App' => 'Illuminate\Support\Facades\App',
8 'Artisan' => 'Illuminate\Support\Facades\Artisan',
9 'Auth' => 'Illuminate\Support\Facades\Auth',
10 'Blade' => 'Illuminate\Support\Facades\Blade',
11 'Bus' => 'Illuminate\Support\Facades\Bus',
12 'Cache' => 'Illuminate\Support\Facades\Cache',
13 'Config' => 'Illuminate\Support\Facades\Config',
14 'Cookie' => 'Illuminate\Support\Facades\Cookie',
15 'Crypt' => 'Illuminate\Support\Facades\Crypt',
16 'DB' => 'Illuminate\Support\Facades\DB',
17 'Event' => 'Illuminate\Support\Facades\Event',
18 'File' => 'Illuminate\Support\Facades\File',
19 'Gate' => 'Illuminate\Support\Facades\Gate',
20 'Hash' => 'Illuminate\Support\Facades\Hash',
21 'Input' => 'Illuminate\Support\Facades\Input',
22 'Lang' => 'Illuminate\Support\Facades\Lang',
23 'Log' => 'Illuminate\Support\Facades\Log',
24 'Mail' => 'Illuminate\Support\Facades\Mail',
25 'Password' => 'Illuminate\Support\Facades\Password',
26 'Queue' => 'Illuminate\Support\Facades\Queue',
27 'Redirect' => 'Illuminate\Support\Facades\Redirect',
28 'Redis' => 'Illuminate\Support\Facades\Redis',
29 'Request' => 'Illuminate\Support\Facades\Request',
30 'Response' => 'Illuminate\Support\Facades\Response',
31 'Route' => 'Illuminate\Support\Facades\Route',
32 'Schema' => 'Illuminate\Support\Facades\Schema',
33 'Session' => 'Illuminate\Support\Facades\Session',
34 'Storage' => 'Illuminate\Support\Facades\Storage',
35 'URL' => 'Illuminate\Support\Facades\URL',
36 'Validator' => 'Illuminate\Support\Facades\Validator',
37 'View' => 'Illuminate\Support\Facades\View',
38],
39 
40// Other configuration items.

Examining the above code sample, it can be deduced that to add a new facade alias we simply need to add a new entry to the aliases array. The key of the entry will become the name of the alias and the value of the entry will become the class being aliased. To make this clearer, in the above list Response is aliasing Illuminate\Support\Facades\Response, and both classes can be used interchangeably.

We will use our Math facade from earlier, and we will assume it was defined in the Our\Applications \Namespace. We could create an alias like so:

1<?php
2 
3 // Previous alias entries.
4 
5 'Math' => 'Our\Applications\Namespace\Math',
Aliasing Other Classes

Classes, other than facades, can be added to the aliases configuration entry. This will cause them to be available under whatever name was provided, and in the global namespace. Although this can be convenient and useful thing to do, other options should be examined first.

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.