Facade Design Pattern
Let’s look at Gang of Four description of the Facade pattern:
This is a structural pattern as it defines a manner for creating relationships between classes or entities. The facade design pattern is used to define a simplified interface to a more complex subsystem.
According to the Gang of Four the Facade pattern is a structural pattern. The Facade pattern is a class, which wraps a complex library and provides a simpler and more readable interface to it. The facade itself maintains it’s dependencies.
Facades in Laravel
Laravel has a feature similar to this pattern, also named Facades. This name may confuse you because facades in Laravel don’t fully implement the Facade design pattern. According to the documentation:
Facades provide a “static” interface to classes that are available in the application’s service container.
Another words facades serve as a proxy for accessing the container’s services, which is actually the syntactic sugar for these services. Instead of having to go through a testable and maintainable way of instantiating a class, passing in all of its dependencies, we can simply use a static interface, but behind the scenes, Laravel itself will take care of instantiating a class and resolving it’s dependencies out of the IoC container.
We will use Laravel
Cache facade in our examples. Syntax is very clear:
You can achieve the same results with the code below:
As mentioned before, you can use facade classes in Laravel to make services available in a more readable way. In Laravel, all services inside the IoC
container have unique names, and all of them have their own facade class. To access a service from the container you can use
App::make() method or
app() helper function. So there is no difference between these lines of code:
How it works
Let’s take a look at a “real” example of Laravel cache system and
Here we retrieve books from cache with the help of
All facade classes are extended from the base
Facade class. There is only one method, that must be implemented in every facade class:
which returns the unique service name inside the IoC container. So it must return a string, that will be resolved then out of the IoC container.
Here is the source code of the
Illuminate\Support\Facades\Cache facade class:
Ok, but how are we able to do things like below:
It looks like we are calling a static method
Cache class, but as we have seen there is no such static
Cache class. Here method
get() actually exists in the service inside the container.
All the magic is hidden inside the basic
Do your remember the only one method
getFacadeAccessor from the
Cache class? This method returns the name of a
service container binding. When we are referencing any static method on the
Cache facade, Laravel resolves the
cache binding from the service container and runs the requested method against that object.
Now let’s examine this “magic” in details.
Every facade is going to extend the basic abstract
Facade class. The magic is hidden inside three methods here:
__callStatic()- simple PHP magic method
getFacadeRoot()- gets service out of the IoC container
resolveFacadeInstance()- is responsible for resolving the instance of the service
__callStatic() is fired every time when a static method that does not exist on a facade is called. So, after calling
Cache::get('books:popular') we are falling
inside this method, we resolve an instance of the service behind a facade out of the IoC container with the help of
getFacadeRoot() method. Then
we determine the number of arguments was passed to the method and according to this number the required method of the service is called.
getFacadeRoot() returns an instance of the service object behind the facade:
resolveFacadeInstance() method, which is responsible for resolving the proper instance of the service. Here we check passed
argument for an object, then we check if we have already resolved that service. And if not it is simply retrieved out of the container:
And that is all. Actually no magic here.
Instead of writing
Illuminate\Support\Facades\Cache every time when you need to get access to Laravel cache system, you may
Cache and start using it. But how? Again some magic here. We have seen in the source code of
Cache facade, that its
Illuminate\Support\Facades. It becomes possible with the help of aliases. All the aliases of your application are listed in
aliases array in
Here you can see that each alias name is mapped to a fully-qualified class name. We can use any name for
a facade class. Now it becomes clear, that Laravel itself loads this array of aliases. This process happens in
Illuminate\Foundation\AliasLoader service. It takes the
aliases array, then creates a stack of PHP’s
spl_autoload_register function call:
In this stack each function creates an alias for the respective facade class by using PHP’s
And that’s all the magic with autoloading. Next time, when we try to access a facade class, that doesn’t exist, PHP will check
__autoload functions stack to get a necessary autoloader. By this time
AliasLoader has already registered everything.
According to the
aliases array from
config/app.php each autoloader resolves original class and then creates an alias for it.
So, next time when you write something like this:
you should understand that behind the scenes
Cache is resolved by Laravel to
Create a Custom Facade
Now when we have understood the magic behind facades, it’s time to create our own one. This process is very simple and consists of four steps:
- create a service class
- bind it to the IoC container
- create a facade class
- configure a facade alias configuration
We start with a service class. For example, we’ll create a
Stripe service for processing payments in out application:
To use facades we need to be able to resolve this class out of the IoC container, so let’s create a binding.
The best place to put this a binding is a custom service provider. For example, we create
add this binding in a
Now we must configure Laravel to load our new service provider. Add it to
providers array in the
Next, we can create our own facade class. Let’s put it in
Finally, we can add an alias for our facades in
aliases array in the
That’s all, we have successfully created a Laravel facade. Feel free to test it. Now there is no more magic about
facades for us. We have traveled from using
Cache facade and understanding how it works to creating our own