02. Understanding Laravel — Facades

02. Understanding Laravel — Facades

Laravel is set up in a way that allows the developer to get up to speed as fast as possible and thus it comes with a lot of features baked in by default. Because of its huge size, you may think that it has a very steep learning curve and not very friendly to beginner developers, requiring you to learn a whole bunch of things before you become productive using it. Especially if you have never worked with any framework before: like it was in my case.

Worry not though because Laravel comes with a feature called facades, not to be confused with the Facade Design Pattern, that allows you to access a complicated or confusing back-end using a simplified API. In the previous post, I talked about the Laravel Service Container, what it is: exemplified it to a toolbox, and how to add objects to it. Laravel has lots of default features that you can access through methods on objects that are added into the service container.

If you want to get an object from the service container though you have to know the class or interface name that was used when binding it into the container. If you are going to take advantage of the service container you need to understand dependency injection, a concept that many beginner developers are not aware of or why we need it in the first place.

Laravel facades, however, provide very short and ubiquitous names to almost all instances that are bound to the service container. This means you can get started taking advantage of Laravel features using short and memorable names without using dependency injection at all. For example instead of having to type something like 👇:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Contracts\Routing\ResponseFactory;

class ShowWelcomePageController extends Controller
{

    /**
     * Show the application welcome page
     *
     * @return Response $response
     */
    public function __invoke()
    {
         $response = app()
           ->make(ResponseFactory::class)
           ->view('welcome');
           
         return $response;
    }
}

all you will have to do is something like 👇, and in both cases, you will have the same effect.

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class ShowWelcomePageController extends Controller
{

    /**
     * Show the application welcome page
     *
     * @return Response $response
     */
    public function __invoke()
    {      
         return Response::view('welcome');
    }
}

You can think of a facade as a short nickname you give to your friend so that instead of calling him {{ some complicated name }} you can just use the short nickname instead. Under the hood, you are still calling the same person and they can respond to both names and, in both cases, they will respond the same. Similarly, a facade will allow you to get an object from the service container and use its methods using a very terse and memorable syntax.


How facades work

To make you understand how facades work, I thought it would be better if we manually create a facade for an imaginary service, with a really bad name. Default Laravel facades are implemented and used in the same way and you can go over them here to see a list of some functionalities that come backed with Laravel.

Let’s say we have a service class with a really long name PoorlyNamedFooService that has a method called doSomething that we need to use in our controller. Without dependency injection we do this 👇:

<?php

...

public function methodName() {
    $fooService = new PoorlyNamedFooServiceImplementation(
       $arg1, $arg2, ..., $argN);
       
    $result = $fooService->doSomething();
}

OR if we had bound an implementation of the PoorlyNamedFooService into the service container using a service provider 👇:

<?php

...

public function methodName() {
    $fooService = app()->make(PoorlyNamedFooService::class);
    $result = $fooService->doSomething();
}

...

With dependency injection, we do this 👇, and Laravel will automatically do the resolving for us:


<?php

...

private $fooService;

public function __construct(PoorlyNamedFooService $fooService) {
    $this->fooService = $fooService;
}

public function methodName() {
    $result = $this->fooService->doSomething();
}

...

And when we are using a facade this is what we do 👇:

<?php

...

pubclic function methodName(){
    $result = FooService::doSomething();
}

...

To create a facade for our PoorlyNamedFooService, first, let’s make sure that we bind an instance of the PoorlyNamedFooServiceImplementation into the Laravel Service Container, we do this inside the register method of the FooServiceProvider class which we can create using the make:provider artisan command.

$ php artisan make:provider FooServiceProvider
<?php

...

public function register()
{
    $this->app->bind(
      PoorlyNamedFooService::class, 
      function ($app) {
        return new PoorlyNamedFooServiceImplementation(
          $arg1, $arg2, ..., $argN);
    });
}

...

Now to the meat of this post. To create the facade, all we have to do is create a class named FooService that extends the \Illuminate\Support\Facades\Facade abstract class, and then implement the template method: see Template Method Design Pattern: getFacadeAccessor(), which should return the name of a service container binding i.e the name we used when binding an instance of PoorlyNamedFooService to the container. Which in this case is PoorlyNamedFooService::class . 👇

<?php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class FooService extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return PoorlyNamedFooService::class;
    }
}

Now when you call the static method doSomething on the FooService facade anywhere in your code, Laravel will first resolve the PoorlyNamedFooService::class binding from the container, and then runs the doSomething method against that resolved instance. You can see the mechanics of how this all works by reading the official Laravel docs or by inspecting how the abstract Facade class is implemented. As you can see, under the hood we are still calling the original doSomething() method from the PoorlyNamedFooServiceImplementation and returning its results. But in this case, we have used some kind of proxy: the facade, to that object so we can use it’s methods easily, without having to remember long class names.

The resolveFacadeInstance() method of the abstract Facade class, implements the Singleton Design Pattern

Conclusion

There’s a lot of debate going around all over the internet about whether to use Laravel’s facades or not. Some practitioners think they tie you into a framework, some have their valid reasons. Laravel itself advises against excessive reliance on them, and to consider other alternatives like dependency injection as illustrated earlier. Excessive use of facades may cause class scope creep and before you know it you have a class that does too many things and violating the Single Responsibility Principle. Using dependency injection, however, you get a visual feedback of just how many dependencies your class has and if it is now time to refactor.

I think facades are a great feature provided by Laravel, although as it is advised some extra care must be taken when using them. Them leading to badly designed code doesn’t mean they are bad, it just means you are using them the wrong way and they should not be blamed for that. A loose recommendation I would give is to only limit their use down to the controllers, and other parts of your application that are framework dependent. Remember to keep your controllers as thin as possible by pushing all your business logic to a framework agnostic domain model as advised by Domain Driven Design, a topic of another day. This way you know even if you decide to switch to a completely different framework in the future, at least you won’t have to do a complete rewrite, and the important parts of your application will still work fine.

Laravel is only opinionated down to the controllers everything else below is up to you. You can even swap Eloquent ORM for another ORM if you wish to.

One mistake that a developer can do is to write domain logic that is too tied to a particular framework making it very hard to update to a new version or to switch to a framework if need be. Domain logic rarely changes, frameworks, however, can change twice every year or more, always strive to write code that makes the switch easier, so you can take advantage of major updates and security fixes. Will you be able to update to a new framework if need be, or if you realize there’s a better alternative to a framework you are currently using, does your code allow for an easy switch? Always remember to ask yourself these questions when writing your code. The framework should bend to support your domain logic and not vice versa.

In addition to facades, Laravel includes a variety of “helper” functions that can perform common tasks. Many of these helper functions perform the same function as a corresponding facade so it’s just a matter of personal taste. For a complete list of every facade and its underlying class, I recommend you to check the official Laravel docs.