Facades
Facades provide a "static" interface to classes that are available in the application's service container. Laravel ships with many facades, and you have probably been using them without even knowing it! Laravel "facades" serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.
Occasionally, you may wish to create your own facades for your application's and packages, so let's explore the concept, development and usage of these classes.
Explanation
In the context of a Laravel application, a facade is a class that provides access to an object from the container. The machinery that makes this work is in the class. Laravel's facades, and any custom facades you create, will extend the base Facade
class.
Your facade class only needs to implement a single method: getFacadeAccessor
. It's the getFacadeAccessor
method's job to define what to resolve from the container. The Facade
base class makes use of the __callStatic()
magic-method to defer calls from your facade to the resolved object.
So, when you make a facade call like Cache::get
, Laravel resolves the Cache manager class out of the service container and calls the get
method on the class. In technical terms, Laravel Facades are a convenient syntax for using the Laravel service container as a service locator.
However, if we look at that Illuminate\Support\Facades\Cache
class, you'll see that there is no static method get
:
class Cache extends Facade {
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'cache'; }
}
The Cache class extends the base Facade
class and defines a method getFacadeAccessor()
. Remember, this method's job is to return the name of a service container binding.
When a user references any static method on the Cache
facade, Laravel resolves the cache
binding from the service container and runs the requested method (in this case, get
) against that object.
So, our Cache::get
call could be re-written like so:
Importing Facades
Remember, if you are using a facade in a controller that is namespaced, you will need to import the facade class into the namespace. All facades live in the global namespace:
<?php namespace App\Http\Controllers;
use Cache;
class PhotosController extends Controller {
/**
* Get all of the application photos.
*
*/
public function index()
{
$photos = Cache::get('photos');
//
}
}
Creating Facades
Creating a facade for your own application or package is simple. You only need 3 things:
- A service container binding.
- A facade class.
- A facade alias configuration.
Let's look at an example. Here, we have a class defined as PaymentGateway\Payment
.
App::bind('payment', function()
{
return new \PaymentGateway\Payment;
});
A great place to register this binding would be to create a new named PaymentServiceProvider
, and add this binding to the register
method. You can then configure Laravel to load your service provider from the config/app.php
configuration file.
Next, we can create our own facade class:
Finally, if we wish, we can add an alias for our facade to the aliases
array in the config/app.php
configuration file. Now, we can call the process
method on an instance of the Payment
class.
Classes in the aliases
array are not available in some instances because PHP will not attempt to autoload undefined type-hinted classes. If \ServiceWrapper\ApiTimeoutException
is aliased to , a catch(ApiTimeoutException $e)
outside of the namespace \ServiceWrapper
will never catch the exception, even if one is thrown. A similar problem is found in classes which have type hints to aliased classes. The only workaround is to forego aliasing and use
the classes you wish to type hint at the top of each file which requires them.
Unit testing is an important aspect of why facades work the way that they do. In fact, testability is the primary reason for facades to even exist. For more information, check out the mocking facades section of the documentation.
Facade Class Reference
Below you will find every facade and its underlying class. This is a useful tool for quickly digging into the API documentation for a given facade root. The key is also included where applicable.