April 21, 2018 —John Koster
Facades are a convenient way to access Laravel's components. Each facade is bound to some component already registered in the service container. Facades are typically used to provide a simpler interface to an complex underlying subsystem. While some facades provide "shortcut" methods, most of Laravel's facades act like proxies by providing a static interface to an actual class instance.
All of the default facades are located within the "Illuminate\Support\Facades" namespace and can be located within the vendor/laravel/framework/src/Illuminate/Support/Facades
directory. Every facade extends the abstract Facade
("Illuminate\Support\Facades\Facade") class and must provide a getFacadeAccessor()
method which is defined to be protected.
The getFacadeAccessor()
method indicates what class or component should be resolved from the service container when the facade is accessed. All method calls are then redirected to that class instance[^facade-instance-methods]. Laravel refers to this class instance as the facade root.
Facade roots are the class instance that is bound in the service container. For example, the Auth
facade redirects all method calls to an instance of "Illuminate\Auth\AuthManager", which the service container resolves with the auth
binding.
[^facade-instance-methods]: Some facades define additional static methods that may are not necessarily part of the underlying component or class. In these instances, the static method (that belongs to the facade) is called directly. One such example is the Cookie
facade.
Each facade has an alias. An alias in PHP is just a shortcut to a longer class name. For example, when we use
something as something else, we are creating a class alias:
1use Some\ReallyReallyLongClassName as ShorterName;
In the above example ShorterName
is an alias of ReallyReallyLongClassName
. Laravel creates aliases for all of the facades automatically, and the entire list of them can be found in the aliases
array in the config/app.php
file. The aliases that Laravel creates are in the global namespace, which means that developers can write code that looks like this:
1<?php2 3namespace App\Http\Controllers;4 5use Input;6 7// Other code here.
instead of having to write code that references the full namespace:
1<?php2 3namespace App\Http\Controllers;4 5use Illuminate\Support\Facades\Input;6 7// Other code here.
Fully qualified names, such as "Illuminate\Support\Facades\Input" are longer, but offer greater clarity on what class is being imported. At the end of the day, it comes down to personal preference.
Laravel's facades are used just like any other static class, with the exception that facades are redirecting method calls to an actual class instance. Facades are typically imported at the top of the source file, along with any other classes that are required.
For example, using a facade to retrieve an item from the cache:
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Support\Facades\Cache; 6 7class ExampleController extends Controller { 8 9 public function getIndex()10 {11 $cachedItem = Cache::get('some_cache_item');12 }13 14}
The alternative[^facade-alternatives] is to inject the cache repository directly into the controller:
[^facade-alternatives]: Dependency injection is not the only alternative to using facades, it is, however, arguably the most common in Laravel projects.
1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Cache\Repository as CacheRepository; 6 7class ExampleController extends Controller { 8 9 /**10 * The cache repository.11 12 * @var CacheRepository13 */14 protected $cacheRepository = null;15 16 public function __construct(17 CacheRepository $cacheRepository18 )19 {20 $this->cacheRepository = $cacheRepository;21 }22 23 public function getIndex()24 {25 $cachedItem = $this->cacheRepository26 ->get('some_cache_item');27 }28 29}
Both code examples would accomplish the same thing: retrieve some_cache_item
from the cache storage. The facade example allows for shorter code, and code that is definitely easier to follow along with. The second example has its own advantages too, which will not be covered in this section.
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 $secondNumber10 * @return mixed11 */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:
1App::singleton('math', function()2{3 return new Calculator;4});
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 string11 */12 protected static function getFacadeAccessor()13 {14 return 'math';15 }16 17}
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 2 3namespace App\Http\Controllers; 4 5use Calculator; 6 7class TestController extends Controller { 8 9 public function getIndex()10 {11 // We will create an instance, instead of having12 // it supplied through the constructor.13 $calculator = new Calculator;14 15 $result = $calculator->add(1, 2);16 }17 18}
now using the facade:
1<?php 2 3namespace App\Http\Controllers; 4 5use Math; 6 7class TestController extends Controller { 8 9 public function getindex()10 {11 $result = Math::add(1, 2);12 }13 14}
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 similar to the following example:
1<?php 2 3// Other configuration items. 4 5'aliases' => [ 6 7 'App' => Illuminate\Support\Facades\App::class, 8 'Artisan' => Illuminate\Support\Facades\Artisan::class, 9 'Auth' => Illuminate\Support\Facades\Auth::class,10 'Blade' => Illuminate\Support\Facades\Blade::class,11 'Broadcast' => Illuminate\Support\Facades\Broadcast::class,12 'Bus' => Illuminate\Support\Facades\Bus::class,13 'Cache' => Illuminate\Support\Facades\Cache::class,14 'Config' => Illuminate\Support\Facades\Config::class,15 'Cookie' => Illuminate\Support\Facades\Cookie::class,16 'Crypt' => Illuminate\Support\Facades\Crypt::class,17 'DB' => Illuminate\Support\Facades\DB::class,18 'Eloquent' => Illuminate\Database\Eloquent\Model::class,19 'Event' => Illuminate\Support\Facades\Event::class,20 'File' => Illuminate\Support\Facades\File::class,21 'Gate' => Illuminate\Support\Facades\Gate::class,22 'Hash' => Illuminate\Support\Facades\Hash::class,23 'Lang' => Illuminate\Support\Facades\Lang::class,24 'Log' => Illuminate\Support\Facades\Log::class,25 'Mail' => Illuminate\Support\Facades\Mail::class,26 'Notification'27 => Illuminate\Support\Facades\Notification::class,28 'Password' => Illuminate\Support\Facades\Password::class,29 'Queue' => Illuminate\Support\Facades\Queue::class,30 'Redirect' => Illuminate\Support\Facades\Redirect::class,31 'Redis' => Illuminate\Support\Facades\Redis::class,32 'Request' => Illuminate\Support\Facades\Request::class,33 'Response' => Illuminate\Support\Facades\Response::class,34 'Route' => Illuminate\Support\Facades\Route::class,35 'Schema' => Illuminate\Support\Facades\Schema::class,36 'Session' => Illuminate\Support\Facades\Session::class,37 'Storage' => Illuminate\Support\Facades\Storage::class,38 'URL' => Illuminate\Support\Facades\URL::class,39 'Validator' => Illuminate\Support\Facades\Validator::class,40 'View' => Illuminate\Support\Facades\View::class,41 42],43 44// 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// Previous alias entries.2 3'Math' => 'Our\Applications\Namespace\Math',
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.
The following tables will list all the facades that are available by default. In addition, they will display the name of the service container binding as well as the class behind the facade. If a particular facade provides additional methods (that are not necessarily available in the underlying class), it will appear in the third table "Facades Providing Additional Methods". Any additional methods will be explained later in the section.
Facade Service Container Binding:
Facade | Service Container Binding |
---|---|
App | app |
Artisan | Illuminate\Contracts\Console\Kernel |
Auth | auth |
Blade | See "Notes on Blade" |
Broadcast | Illuminate\Contracts\Broadcasting\Factory |
Bus | Illuminate\Contracts\Bus\Dispatcher |
Cache | cache |
Config | config |
Cookie | cookie |
Crypt | encrypter |
DB | db |
Event | events |
File | files |
Gate | Illuminate\Contracts\Auth\Access\Gate |
Hash | hash |
Input | request |
Lang | translator |
Log | Psr\Log\LoggerInterface |
mailer |
|
Notification | Illuminate\Notifications\ChannelManager |
Password | auth.password |
Queue | queue |
Redirect | redirect |
Redis | redis |
Request | request |
Response | Illuminate\Contracts\Routing\ResponseFactory |
Route | router |
Schema | See "Notes on Schema" |
Session | session |
Storage | filesystem |
URL | url |
Validator | validator |
View | view |
Facade Class Reference:
Alias | Resolved 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 |
Cookie | Illuminate\Support\Facades\Cookie |
Crypt | Illuminate\Support\Facades\Crypt |
DB | Illuminate\Support\Facades\DB |
Eloquent | Illuminate\Database\Eloquent\Model |
Event | Illuminate\Support\Facades\Event |
File | Illuminate\Support\Facades\File |
Gate | Illuminate\Support\Facades\Gate |
Hash | Illuminate\Support\Facades\Hash |
Lang | Illuminate\Support\Facades\Lang |
Log | Illuminate\Support\Facades\Log |
Illuminate\Support\Facades\Mail | |
Notification | Illuminate\Support\Facades\Notification |
Password | Illuminate\Support\Facades\Password |
Queue | Illuminate\Support\Facades\Queue |
Redirect | Illuminate\Support\Facades\Redirect |
Redis | Illuminate\Support\Facades\Redis |
Request | Illuminate\Support\Facades\Request |
Response | Illuminate\Support\Facades\Response |
Route | Illuminate\Support\Facades\Route |
Schema | Illuminate\Support\Facades\Schema |
Session | Illuminate\Support\Facades\Session |
Storage | Illuminate\Support\Facades\Storage |
URL | Illuminate\Support\Facades\URL |
Validator | Illuminate\Support\Facades\Validator |
View | Illuminate\Support\Facades\View |
Facades Providing Additional Methods:
Facade | Number of Additional Methods |
---|---|
Cookie | 2 |
Input | 2 |
Schema | 2 |
Blade
Most facades request a concrete class implementation from the service container based off of some abstract string representation. However, the Blade
facade retrieve an "Illuminate\View\Engines\EngineResolver" instance from the Illuminate\View\Factory.
The "Illuminate\View\Engines\EngineResolver" is a class that returns template compilers based on a given key name. By default, the following compilers and engines are available:
Compiler/Engine Name | Concrete Class Implementation |
---|---|
php |
Illuminate\View\Engines\PhpEngine |
blade |
Illuminate\View\Compilers\BladeCompiler |
Developers can manually create an instance of the BladeCompiler
themselves like so (this sample is provided for demonstration purposes):
1<?php2 3use Illuminate\Support\Facades\App;4 5$bladeCompiler = App::make('view')->getEngineResolver()6 ->resolve('blade')->getCompiler();
Schema
Like the Blade
facade, the Schema
facade does not simply resolve some instance from the service container. The Schema
facade returns an instance of "Illuminate\Database\Schema\Builder" configured to use the default connection that appears in the database database configuration.
Cookie
MethodsThe Cookie
facade defines two additional methods. These methods access other, related, components. These methods exist to simplify accessing related components.
has($key)
The has
function will check if a cookie with the given $key
exists for the current request.
get($key, $default = null)
The get
function will retrieve a cookie from the current request with the given $key
. A $default
value can be supplied and will be returned if a cookie with the given $key
does not exist.
Input
MethodsThe Input
facade defines one extra method. Facades define extra methods to provide simpler access to underlying sub-systems, or to call functions on other, related components.
get($key = null, $default = null)
The get
method will get an item from the input data, such as when a user posts a form or an API request is being processed. The get
method can be used for requests with the following HTTP verbs:
The get
method will invoke the input
method on an instance of the Illuminate\Http\Request class.
The get
method looks up the data based on the given $key
. A $default
value can be supplied and will be returned if the given $key
is not found in the request data.
Schema
MethodsThe Schema
facade defines one extra method. Facades define extra methods to provide simpler access to underlying sub-systems, or to call functions on other, related components, or to provide greater testability of the framework components.
connection($name)
The connection
method will return a new schema builder ("Illuminate\Database\Schema\Builder") instance for the given connection. The $name
is the name of the connection as it appears in the database configuration file.
Notification
MethodsThe Notification
facade defines a few extra methods that can be called without resolving the notification sub-system from the service container. Facades define extra methods to provide simpler access to underlying sub-systems, or to call functions on other, related components, or to provide greater testability of the framework components.
fake()
The fake
method will swap the currently bound notification channel manager instance with a fake; this is incredibly useful for testing purposes. The fake notification manager instance, by default, is an instance of "Illuminate\Support\Testing\Fakes\NotificationFake".
route($channel, $route)
The route
method allows for the sending of notifications in an ad-hoc fashion. The following example demonstrates the basic usage of the route
method for sending a notification to someone who has purchased something:
1Notification::route('mail', 'john@stillat.com')2 ->notify(new MeerkatLicense($license));
Queue
MethodsThe Queue
facade defines one extra method to help make testing queue functionality within your applications easier.
fake()
The fake
method will swap the currently bound queue manager instance with a fake; this is incredibly useful for testing purposes. The fake queue manager instance, by default, is an instance of "Illuminate\Support\Testing\Fakes\QueueFake".
Storage
MethodsThe Storage
facade defines a few extra helper methods, both are to help make testing filesystem components within your Laravel application easier. Both of these testing methods will replace the storage disk with a local storage disk; this means that if your application takes advantage of services such as Amazon S3, you can use local testing disks during your day-to-day testing to keep your service usage minimal.
fake($disk = null)
The fake
method will replace the provided $disk
with a local testing disk. The local disk will be stored in your application storage path under the sub-directory location framework/testing/disks/<DISK_NAME>
.
The local directory will be cleared each time the fake
method is invoked with that disk's name.
persistentFake($disk = null)
The persistentFake
method will replace the provided $disk
with a local testing disk. The local disk will be stored in your application storage path under the sub-directory location framework/testing/disks/<DISK_NAME>
.
The persistent local directory will not be cleared each time the persistentFake
method is invoked with that disk's name.
It is possible to quickly resolve the class behind a facade. Facades expose a public method getFacadeRoot
which will return the instance of the underlying object the facade is forwarding method calls to. It is convenient that getFacadeRoot
returns an object instance because PHP's get_class
method can then be used to retrieve the fully-qualified name of the facade's underlying class implementation.
1// Getting the class name of the underlying facade instance.2$className = get_class(Auth::getFacadeRoot());
In the above code example, the $className
variable would contain the value "Illuminate\Auth\AuthManager".
This method of determining a facade's underlying class can be expanded on to create a function that will list every facade's underlying class for the current Laravel installation. We will do this by creating three functions, each newer one building on the previous function.
The first function we will create, getFacadeClasses
will return a collection associating each facade alias with its concrete implementation, if available. If no concrete implementation can be resolved from the service container, the abstract reference is returned instead:
1/** 2 * Returns a collection of facade aliases 3 * and their concrete class names. 4 * 5 * @return \Illuminate\Support\Collection 6 */ 7function getFacadeClasses() { 8 return collect(config('app.aliases')) 9 ->map(function ($abstract, $alias) {10 try {11 // Attempt to return the name of12 // the concrete implementation.13 return get_class(app($abstract));14 } catch (Exception $e) {15 // Fall back to the abstract.16 return $abstract;17 }18 });19}
The second function we will create generate the Markdown syntax for a table listing the facade aliases and their resolved classes. This function will make use of many of the collection's features:
1/** 2 * Returns Markdown table markup for facade 3 * aliases and their concrete class names. 4 * @return string 5 */ 6function getFacadeClassMarkdown() { 7 return collect([ 8 ['line' => '| Alias | Resolved Class |'], 9 ['line' => '|---|---|']10 ])->concat(getFacadeClasses()11 ->map(function ($resolvedClass, $alias) {12 return [13 'line' =>14 "| {$alias} | {$resolvedClass} |"15 ];16 })17 )->implode('line', PHP_EOL);18}
The third, and final function we will create will convert the Markdown output from our getFacadeClassMarkdown
function into HTML using Laravel's mailer markdown parse method:
1/** 2 * Returns an HTML table containing the facade aliases 3 * and their concrete class names, if available. 4 * 5 * @return string 6 */ 7function getFacadeClassHtmlTable() { 8 return \Illuminate\Mail\Markdown 9 ::parse(getFacadeClassMarkdown());10}
If we were to return the results of the getFacadeClassHtmlTable
function from a route or controller action, we would see output similar to the following in the browser's source window:
1<table> 2 <thead> 3 <tr> 4 <th>Alias</th> 5 <th>Resolved Class</th> 6 </tr> 7 </thead> 8 <tbody> 9 <tr> 10 <td>App</td> 11 <td>Illuminate\Support\Facades\App</td> 12 </tr> 13 <tr> 14 <td>Artisan</td> 15 <td>Illuminate\Support\Facades\Artisan</td> 16 </tr> 17 <tr> 18 <td>Auth</td> 19 <td>Illuminate\Support\Facades\Auth</td> 20 </tr> 21 <tr> 22 <td>Blade</td> 23 <td>Illuminate\Support\Facades\Blade</td> 24 </tr> 25 <tr> 26 <td>Broadcast</td> 27 <td>Illuminate\Support\Facades\Broadcast</td> 28 </tr> 29 <tr> 30 <td>Bus</td> 31 <td>Illuminate\Support\Facades\Bus</td> 32 </tr> 33 <tr> 34 <td>Cache</td> 35 <td>Illuminate\Support\Facades\Cache</td> 36 </tr> 37 <tr> 38 <td>Config</td> 39 <td>Illuminate\Support\Facades\Config</td> 40 </tr> 41 <tr> 42 <td>Cookie</td> 43 <td>Illuminate\Support\Facades\Cookie</td> 44 </tr> 45 <tr> 46 <td>Crypt</td> 47 <td>Illuminate\Support\Facades\Crypt</td> 48 </tr> 49 <tr> 50 <td>DB</td> 51 <td>Illuminate\Support\Facades\DB</td> 52 </tr> 53 <tr> 54 <td>Eloquent</td> 55 <td>Illuminate\Database\Eloquent\Model</td> 56 </tr> 57 <tr> 58 <td>Event</td> 59 <td>Illuminate\Support\Facades\Event</td> 60 </tr> 61 <tr> 62 <td>File</td> 63 <td>Illuminate\Support\Facades\File</td> 64 </tr> 65 <tr> 66 <td>Gate</td> 67 <td>Illuminate\Support\Facades\Gate</td> 68 </tr> 69 <tr> 70 <td>Hash</td> 71 <td>Illuminate\Support\Facades\Hash</td> 72 </tr> 73 <tr> 74 <td>Lang</td> 75 <td>Illuminate\Support\Facades\Lang</td> 76 </tr> 77 <tr> 78 <td>Log</td> 79 <td>Illuminate\Support\Facades\Log</td> 80 </tr> 81 <tr> 82 <td>Mail</td> 83 <td>Illuminate\Support\Facades\Mail</td> 84 </tr> 85 <tr> 86 <td>Notification</td> 87 <td>Illuminate\Support\Facades\Notification</td> 88 </tr> 89 <tr> 90 <td>Password</td> 91 <td>Illuminate\Support\Facades\Password</td> 92 </tr> 93 <tr> 94 <td>Queue</td> 95 <td>Illuminate\Support\Facades\Queue</td> 96 </tr> 97 <tr> 98 <td>Redirect</td> 99 <td>Illuminate\Support\Facades\Redirect</td>100 </tr>101 <tr>102 <td>Redis</td>103 <td>Illuminate\Support\Facades\Redis</td>104 </tr>105 <tr>106 <td>Request</td>107 <td>Illuminate\Support\Facades\Request</td>108 </tr>109 <tr>110 <td>Response</td>111 <td>Illuminate\Support\Facades\Response</td>112 </tr>113 <tr>114 <td>Route</td>115 <td>Illuminate\Support\Facades\Route</td>116 </tr>117 <tr>118 <td>Schema</td>119 <td>Illuminate\Support\Facades\Schema</td>120 </tr>121 <tr>122 <td>Session</td>123 <td>Illuminate\Support\Facades\Session</td>124 </tr>125 <tr>126 <td>Storage</td>127 <td>Illuminate\Support\Facades\Storage</td>128 </tr>129 <tr>130 <td>URL</td>131 <td>Illuminate\Support\Facades\URL</td>132 </tr>133 <tr>134 <td>Validator</td>135 <td>Illuminate\Support\Facades\Validator</td>136 </tr>137 <tr>138 <td>View</td>139 <td>Illuminate\Support\Facades\View</td>140 </tr>141 </tbody>142</table>
∎
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.