What is Laravel Facades

Ali
4 min readJul 20, 2021

--

Facade Design Pattern:

Facade pattern hides the complexities of the system and provides an interface to the client using which the client can access the system.

It flies right over my head huh! So what Facade design pattern is essentially saying is that I will provide huge functionality to you, you just have to ask. It’s just like using a library which does all the heavy lifting but you just have to ask the library via its fluent API/functions.

In above example FacadePatternDemo is asking for functionality using one central class ShapeMaker. Whenever you need functionality you always go to a central place ShapeMaker (it’s like one stop shop). Now the thing on the left can grow in complexity and maybe dependant on several additional layers which are not shown here; but you are not are not concerned with this as long as you keep on asking from your central class (the interface to the complex functionality).

Facades in Laravel:

Facades provide a “static” interface to classes that are available in the application’s service container. I can’t understand this either at least in the start!, let’s break it down:

Laravel does two things; it’s saying I will not only provide the huge complex functionality, but also give you way of asking me in such a way which is less work and is beautiful to write.

Consider:

class Greet {

public function sayHi($message){
return $message;
}
}

Now how would you use Greet:

$greet = new Greet(); 
$greet->sayHi('Hi');

Laravel’s facade way of say this is:

Greet::sayHi('Hi'); // beautiful and less work (the ‘terse’ syntax)

Now before I tell you how it works we need to know the service container.

For starters it is just a global big array of key values; consider this

['Greet' => new Greet()];

Laravel uses PHP mechanism ‘Reflection API’ under the hood to resolve the classes. What we are saying here is that every time I ask for key ‘Greet’ anywhere in my app, Laravel knows how to resolve it and would give me an instance of Greet class.

Now how it is calling ‘sayHi’ statically although we haven’t defined it on Greet class.

To understand this we need to know __callStatic a PHP magic method. So if we called a static method which is not available on the class, this method will be fired by PHP for us automatically.

Consider manual Facade implementation for our Greet class; so the pattern here is if we want a ‘Facade’ for a class we would have a facade class with same name but prefixed with namespace Facades\; and in there we must have __callStatic function implemented.

class Greet{public function sayHi($message){ 
return $message;
}
}
class Facades\Greet{public static function __callStatic($method, $args){

//so calling Greet::sayHi('Hi') would land here
return app()['Greet']->$method(...$args); Note: we used ->$method NOT ->method which is dynamic
it will resolve 'Greet' class out of the container and call
method dynamically 'sayHi' with arguments 'Hi'. So it's a
fancy technique by Laravel which is proxying the underlying
class to support terse syntax and less work.
}
}

So we used the core functionality of the Greet class without instantiating it.

Laravel also helps us making any class a Facade, we just have to extend it from lluminate\Support\Facades\Facade and override a function: getFacadeAccessor like so:

class Facade\Greet extends lluminate\Support\Facades\Facade{
public function getFacadeAccessor(){
// this is a replacement calling __callStatic manually,
// all we have to tell which class to return
// it will resolve the class for us, call the method on it
// and pass the arguments. All we have to tell it how to resolve it

return new Greet;
}
}

Greet::sayHi(‘Hi’) end up like this: (new Greet)->sayHi(‘Hi’).

So why is this important:

Let us assume we have a model called Car like this:

class Car extends Model{
// …
}

If you look closely you will see __callStatic method on Model class as well. Because we are extending from Model, all the things that a Model class can do, Car class can do it as well. For example we can say in our controller:

Car::create(request()->all());

In above what it did was determined which class needs to be instantiated (proxying underlining class) and then call the create method on it by passing request data. We called a create method statically on Car class which is not present statically on Car or extending class Model, but we do have a create public method in framework source Illuminate\Database\Eloquent\Builder which the Model class is using. So we removed the need for instantiating Car class and then calling create method statically which less work and terse syntax of course :-)

--

--

No responses yet