Laravel 5 Facades

22 min read

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.

Facade Aliases and Importing Facades

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:

use 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:

<?php

namespace App\Http\Controllers;

use Input;

// Other code here.

instead of having to write code that references the full namespace:

<?php
    
namespace App\Http\Controllers;

use Illuminate\Support\Facades\Input;

// Other code here.

Fully Qualified Names vs. Aliases

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.

Using Facades

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:

<?php
    
namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class ExampleController extends Controller {

    public function getIndex()
    {
        $cachedItem = Cache::get('some_cache_item');
    }

}

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.

<?php
    
namespace App\Http\Controllers;

use Illuminate\Cache\Repository as CacheRepository;

class ExampleController extends Controller {

    /**
     * The cache repository.

     * @var CacheRepository
     */
    protected $cacheRepository = null;

    public function __construct(
        CacheRepository $cacheRepository
    )
    {
        $this->cacheRepository = $cacheRepository;
    }

    public function getIndex()
    {
        $cachedItem = $this->cacheRepository
            ->get('some_cache_item');
    }

}

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.

Creating Facades

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:

<?php

class Calculator {

    /**
     * Adds two numbers.

     * @param  mixed $firstNumber
     * @param  mixed $secondNumber
     * @return mixed
     */
    public function add($firstNumber, $secondNumber)
    {
        return $firstNumber + $secondNumber;
    }

    // Possibly many more methods.

}

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

App::singleton('math', function()
{
    return new Calculator;
});

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:

<?php

use Illuminate\Support\Facades\Facade;

class Math extends Facade {

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'math';
    }

}

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:

<?php
    
namespace App\Http\Controllers;

use Calculator;

class TestController extends Controller {

    public function getIndex()
    {
        // We will create an instance, instead of having
        // it supplied through the constructor.
        $calculator = new Calculator;

        $result = $calculator->add(1, 2);
    }

}

now using the facade:

<?php
    
namespace App\Http\Controllers;

use Math;

class TestController extends Controller {

    public function getindex()
    {
        $result = Math::add(1, 2);
    }

}

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 similar to the following example:

<?php

// Other configuration items.

'aliases' => [

    'App' => Illuminate\Support\Facades\App::class,
    'Artisan' => Illuminate\Support\Facades\Artisan::class,
    'Auth' => Illuminate\Support\Facades\Auth::class,
    'Blade' => Illuminate\Support\Facades\Blade::class,
    'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
    'Bus' => Illuminate\Support\Facades\Bus::class,
    'Cache' => Illuminate\Support\Facades\Cache::class,
    'Config' => Illuminate\Support\Facades\Config::class,
    'Cookie' => Illuminate\Support\Facades\Cookie::class,
    'Crypt' => Illuminate\Support\Facades\Crypt::class,
    'DB' => Illuminate\Support\Facades\DB::class,
    'Eloquent' => Illuminate\Database\Eloquent\Model::class,
    'Event' => Illuminate\Support\Facades\Event::class,
    'File' => Illuminate\Support\Facades\File::class,
    'Gate' => Illuminate\Support\Facades\Gate::class,
    'Hash' => Illuminate\Support\Facades\Hash::class,
    'Lang' => Illuminate\Support\Facades\Lang::class,
    'Log' => Illuminate\Support\Facades\Log::class,
    'Mail' => Illuminate\Support\Facades\Mail::class,
    'Notification'
              => Illuminate\Support\Facades\Notification::class,
    'Password' => Illuminate\Support\Facades\Password::class,
    'Queue' => Illuminate\Support\Facades\Queue::class,
    'Redirect' => Illuminate\Support\Facades\Redirect::class,
    'Redis' => Illuminate\Support\Facades\Redis::class,
    'Request' => Illuminate\Support\Facades\Request::class,
    'Response' => Illuminate\Support\Facades\Response::class,
    'Route' => Illuminate\Support\Facades\Route::class,
    'Schema' => Illuminate\Support\Facades\Schema::class,
    'Session' => Illuminate\Support\Facades\Session::class,
    'Storage' => Illuminate\Support\Facades\Storage::class,
    'URL' => Illuminate\Support\Facades\URL::class,
    'Validator' => Illuminate\Support\Facades\Validator::class,
    'View' => Illuminate\Support\Facades\View::class,

],

// 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:

    // Previous alias entries.

    '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.

Facade Class Reference

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
Mail 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
Mail 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

Notes on 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):

<?php

use Illuminate\Support\Facades\App;

$bladeCompiler = App::make('view')->getEngineResolver()
                 ->resolve('blade')->getCompiler();

Notes on 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.

Additional Cookie Methods

The 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.

Additional Input Methods

The 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:

  • GET
  • POST
  • PUT
  • DELETE

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.

Additional Schema Methods

The 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.

Additional Notification Methods

The 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:

Notification::route('mail', 'john@stillat.com')
                ->notify(new MeerkatLicense($license));

Additional Queue Methods

The 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".

Additional Storage Methods

The 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.

Resolving the Class Behind a Facade

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.

// Getting the class name of the underlying facade instance.
$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:

/**
 * Returns a collection of facade aliases
 * and their concrete class names.
 * 
 * @return \Illuminate\Support\Collection
 */
function getFacadeClasses() {
    return collect(config('app.aliases'))
           ->map(function ($abstract, $alias) {
                try {
                    // Attempt to return the name of
                    // the concrete implementation.
                    return get_class(app($abstract));
                } catch (Exception $e) {
                    // Fall back to the abstract.
                    return $abstract;
                }
            });
}

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:

/**
 * Returns Markdown table markup for facade
 * aliases and their concrete class names.
 * @return string
 */
function getFacadeClassMarkdown() {
    return collect([
        ['line' => '| Alias | Resolved Class |'],
        ['line' => '|---|---|']
    ])->concat(getFacadeClasses()
            ->map(function ($resolvedClass, $alias) {
                return [
                    'line' =>
                        "| {$alias} | {$resolvedClass} |"
                ];
            })
    )->implode('line', PHP_EOL);
}

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:

/**
 * Returns an HTML table containing the facade aliases
 * and their concrete class names, if available.
 *
 * @return string
 */
function getFacadeClassHtmlTable() {
    return \Illuminate\Mail\Markdown
                ::parse(getFacadeClassMarkdown());
}

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:

<table>
   <thead>
      <tr>
         <th>Alias</th>
         <th>Resolved Class</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>App</td>
         <td>Illuminate\Support\Facades\App</td>
      </tr>
      <tr>
         <td>Artisan</td>
         <td>Illuminate\Support\Facades\Artisan</td>
      </tr>
      <tr>
         <td>Auth</td>
         <td>Illuminate\Support\Facades\Auth</td>
      </tr>
      <tr>
         <td>Blade</td>
         <td>Illuminate\Support\Facades\Blade</td>
      </tr>
      <tr>
         <td>Broadcast</td>
         <td>Illuminate\Support\Facades\Broadcast</td>
      </tr>
      <tr>
         <td>Bus</td>
         <td>Illuminate\Support\Facades\Bus</td>
      </tr>
      <tr>
         <td>Cache</td>
         <td>Illuminate\Support\Facades\Cache</td>
      </tr>
      <tr>
         <td>Config</td>
         <td>Illuminate\Support\Facades\Config</td>
      </tr>
      <tr>
         <td>Cookie</td>
         <td>Illuminate\Support\Facades\Cookie</td>
      </tr>
      <tr>
         <td>Crypt</td>
         <td>Illuminate\Support\Facades\Crypt</td>
      </tr>
      <tr>
         <td>DB</td>
         <td>Illuminate\Support\Facades\DB</td>
      </tr>
      <tr>
         <td>Eloquent</td>
         <td>Illuminate\Database\Eloquent\Model</td>
      </tr>
      <tr>
         <td>Event</td>
         <td>Illuminate\Support\Facades\Event</td>
      </tr>
      <tr>
         <td>File</td>
         <td>Illuminate\Support\Facades\File</td>
      </tr>
      <tr>
         <td>Gate</td>
         <td>Illuminate\Support\Facades\Gate</td>
      </tr>
      <tr>
         <td>Hash</td>
         <td>Illuminate\Support\Facades\Hash</td>
      </tr>
      <tr>
         <td>Lang</td>
         <td>Illuminate\Support\Facades\Lang</td>
      </tr>
      <tr>
         <td>Log</td>
         <td>Illuminate\Support\Facades\Log</td>
      </tr>
      <tr>
         <td>Mail</td>
         <td>Illuminate\Support\Facades\Mail</td>
      </tr>
      <tr>
         <td>Notification</td>
         <td>Illuminate\Support\Facades\Notification</td>
      </tr>
      <tr>
         <td>Password</td>
         <td>Illuminate\Support\Facades\Password</td>
      </tr>
      <tr>
         <td>Queue</td>
         <td>Illuminate\Support\Facades\Queue</td>
      </tr>
      <tr>
         <td>Redirect</td>
         <td>Illuminate\Support\Facades\Redirect</td>
      </tr>
      <tr>
         <td>Redis</td>
         <td>Illuminate\Support\Facades\Redis</td>
      </tr>
      <tr>
         <td>Request</td>
         <td>Illuminate\Support\Facades\Request</td>
      </tr>
      <tr>
         <td>Response</td>
         <td>Illuminate\Support\Facades\Response</td>
      </tr>
      <tr>
         <td>Route</td>
         <td>Illuminate\Support\Facades\Route</td>
      </tr>
      <tr>
         <td>Schema</td>
         <td>Illuminate\Support\Facades\Schema</td>
      </tr>
      <tr>
         <td>Session</td>
         <td>Illuminate\Support\Facades\Session</td>
      </tr>
      <tr>
         <td>Storage</td>
         <td>Illuminate\Support\Facades\Storage</td>
      </tr>
      <tr>
         <td>URL</td>
         <td>Illuminate\Support\Facades\URL</td>
      </tr>
      <tr>
         <td>Validator</td>
         <td>Illuminate\Support\Facades\Validator</td>
      </tr>
      <tr>
         <td>View</td>
         <td>Illuminate\Support\Facades\View</td>
      </tr>
   </tbody>
</table>

Comments

There are no comments. Be the first to comment!

Up next