PHP
Article

How Laravel Facades Work and How to Use Them Elsewhere

By Reza Lavaryan

The Facade pattern is a software design pattern which is often used in object oriented programming. A facade is, in fact, a class wrapping a complex library to provide a simpler and more readable interface to it. The Facade pattern can also be used to provide a unified and well-designed API to a group of complex and poorly designed APIs.

Facades diagram

The Laravel framework has a feature similar to this pattern, also termed Facades. In this tutorial we will learn how to bring Laravel’s “Facades” to other frameworks. Before we continue, you need to have a basic understanding of Ioc containers.

Let’s first go through the inner working parts of Laravel’s facades, and then we’ll discuss how we can adapt this feature to the other environments.

Facades in Laravel

A Laravel facade is a class which provides a static-like interface to services inside the container. These facades, according to the documentation, serve as a proxy for accessing the underlying implementation of the container’s services.

There have been many debates in the PHP community about this naming, though. Some have argued that the term should be changed in order to avoid confusion of developers, as it doesn’t fully implement the Facade pattern. If this naming confuses you, feel free to call it whatever feels right to you, but please note that the base class that we’re going to use is called Facade in the Laravel framework.

How Facades Are implemented in Laravel

As you probably know, every service inside the container has a unique name. In a Laravel application, to access a service directly from the container, we can use the App::make() method or the app() helper function.

<?php

App::make('some_service')->methodName();

As mentioned earlier, Laravel uses facade classes to make services available to the developer in a more readable way. By using a facade class, we would only need to write the following code to do the same thing:

// ...
someService::methodName();
// ...

In Laravel, all services have a facade class. These facade classes extend the base Facade class which is part of the Illuminate/Support package. The only thing that they need to implement is the getFacadeAccessor method, which returns the service name inside the container.

In the above syntax, someService refers to the facade class. The methodName is in fact a method of the original service in the container. If we look at this syntax outside of the context of Laravel, it would mean that there’s a class named someService exposing a static method named methodName(), but that’s not how Laravel implements this interface. In the next section, we’ll see how Laravel’s base Facade class works behind the scenes.

Base Facade

The Facade class has a private property named $app which stores a reference to the service container. If we need to use facades outside of Laravel, we have to explicitly set the container using setFacadeApplication() method. We’ll get to that shortly.

Inside the base facade class, the __callStatic magic method has been implemented to handle calling of static methods which don’t actually exist. When we call a static method against a Laravel facade class, the __callStatic method is invoked, because the facade class hasn’t implemented that method. Consequently, __callStatic fetches the respective service from the container and calls the method against it.

Here is the implementation of the __callStatic method in the base facade class:

<?php
// ...
/**
     * Handle dynamic, static calls to the object.
     *
     * @param  string  $method
     * @param  array   $args
     * @return mixed
     */
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        switch (count($args)) {
            case 0:
                return $instance->$method();

            case 1:
                return $instance->$method($args[0]);

            case 2:
                return $instance->$method($args[0], $args[1]);

            case 3:
                return $instance->$method($args[0], $args[1], $args[2]);

            case 4:
                return $instance->$method($args[0], $args[1], $args[2], $args[3]);

            default:
                return call_user_func_array([$instance, $method], $args);
        }
    }

In the above method, getFacadeRoot() gets the service from the container.

Anatomy of a Facade Class

Each facade class extends the base class. The only thing that we need to implement is the getFacadeAccessor() method. This method does nothing but return the service’s name in the container.

<?php namespace App\Facades;

use Illuminate\Support\Facades\Facade as BaseFacade;

class SomeServiceFacade extends BaseFacade {

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

}

Aliases

Since Laravel facades are PHP classes, we need to import them before we can use them. Thanks to the namespaces and autoloading support in PHP, all classes are automatically loaded when we access them by the fully-qualified name. PHP also supports aliasing of classes by using the use directive:

use App\Facades\SomeServiceFacade

SomeServiceFacade:SomeMethod();

However, we have to do this in each and every script where we need that particular facade class. Laravel handles the aliasing of facades in its own way by using an alias loader.

How Laravel Aliases the Facades

All alias names are kept in an aliases array inside the app.php config file, which is located inside the /config directory.

If we take a look at the array, we can see that each alias name is mapped to a fully-qualified class name. This means we can use any name that we wish for a facade class:

// ..
'aliases' => [
    // ...
    'FancyName' => 'App\Facades\SomeServiceFacade',
],

Okay, now let’s see how Laravel uses this array for aliasing the facade classes. In the bootstrapping phase, Laravel uses a service named AliasLoader which is part of the Illuminate\Foundation package. AliasLoader takes the aliases array, iterates over all the elements, and creates a queue of __autoload functions using PHP’s spl_autoload_register. Each __autoload function is responsible for creating an alias for the respective facade class by using PHP’s class_alias function.

As a result, we won’t have to import and alias the classes before using them as we normally do with the use directive. So whenever we try to access a class that doesn’t exist, PHP will check the __autoload queue to get the proper autoloader. By that time, AliasLoader has already registered all the __autoload functions. Each autoloader takes a fancy class name and resolves it to the original class name according to the aliases array. Finally, it creates an alias for that class. Consider the following method call:

<?php

// FancyName is resolved to App\Facades\SomeServiceFacade according to the aliases array

FancyName::someMethod()

Behind the scenes, FancyName is resolved to App\Facades\SomeServiceFacade.

Using Facades in Other Frameworks

Okay, now that we have a good understanding of the way Laravel handles its facades and aliases, we can adapt Laravel’s facade approach to other environments. In this article, we’re going to use facades in the Silex framework. However, you can adapt this feature to other frameworks as well by following the same concept.

Silex has its own container, as it extends Pimple. To access a service inside the container, we can use the $app object like so:

<?php
$app['some.service']->someMethod()

With the help of facade classes, we can provide a static-like interface to our Silex services as well. In addition to that, we can use the AliasLoader service to make meaningful aliases for those facades. As a result, we would be able to refactor the above code like so:

<?php
SomeService::someMethod();

Requirements

To use the the base facade class, we need to install the Illuminate\Support package using composer:

composer require illuminate\support

This package contains other services as well, but for now we just need its base Facade class.

Creating the Facades

To create a facade for a service, we just need to extend the base Facade class and implement the getFacadeAccessor method.

For this tutorial, let’s keep all the facades under src/Facades path. As an example, for a service named some.service, the facade class would be as follows:

<?php
namespace App\Facades

use Illuminate\Support\Facades\Facade;

class SomeServiceFacade extends Facade {

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

}

Please note that we have namespaced the class under app\facades.

The only thing that remains is setting the application container on the facade class. As pointed out earlier, when we call a method in a static context against a facade class, __callStatic is triggered. _callStatic uses data returned by getFacadeAccessor() to identify the service inside the container and tries to fetch it. When we’re using the base Facade class outside of Laravel, the container object isn’t set automatically, so we will need to do this manually.

To do this, the base facade class exposes a method named setFacadeApplication which sets the application container for that facade class.

In our app.php file, we need to add the following code:

<?php
Illumiante\Support\Facade::setFacadeApplication($app);

This will set the container for all the facades which are extending the base facade class.

Now, instead of accessing the service from our container, we can use the facade class we just created, also allowing us to call all methods in a static context.

Implementing the Aliases

To alias the facade classes, we’re going to use the AliasLoader that we introduced earlier. Aliasloader is part of the illuminate\foundation package. We can either download the whole package or just borrow the code and keep it as a file.

If you just want to copy the source file, I suggest you keep it under src/Facades. You can namespace the AliasLoader class based on your project’s architecture.

For this example, let’s copy the code and namespace it under app/facades.

Creating the Aliases Array

Let’s create a file in our config directory called aliases.php and put the alias-facade bindings in there like so:

<?php
return [
    'FancyName' => 'App\Facades\SomeService',
];

FancyName is a name that we want to use instead of App\Facades\SomeService.

Registering the Aliases

AliasLoader is a singleton service. To create or get the alias loader’s instance, we need to call the getInstance method with the array of aliases as an argument. Finally, to register all the aliases, we need to call its register method.

Again in the app.php file, add the following code:

<?php

// ...

$aliases = require __DIR__ . '/../../config/aliases.php';
App\Facades\AliasLoader::getInstance($aliases)->register();

And that’s all there is to it! Now we can use the service like so:

<?php
FancyName::methodName();

Wrapping Up

A Facade class only needs to implement the getFacadeAccessor method which returns the service name inside the container. Since we’re using this feature outside of the Laravel environment, we have to explicitly set the service container using the setFacadeApplication() method.

To refer to the facade classes, we either have to use the fully-qualified class names or import them with PHP’s use directive. Alternatively, we can follow Laravel’s way of aliasing the facades by using an alias loader.

Questions? Comments? Leave them below! Thanks for reading!

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

  • http://sputnik.pl Pies

    This kind of code makes it super difficult to debug things, because it’s quite impossible to figure out what actually gets called where. Also, you’re calling non-static classes from something that looks like a static call, which is misleading – you could be writing to a database. I avoid this kind of thing like plague.

    • https://unnikked.ga/ Nicola Malizia

      I completely agree.

    • Reza Lavaryan

      Agree on this with you, but this only applies to codes which don’t use this pattern correctly. Facade concept is meant to simplify complex or poorly designed interfaces for developers.

      If all your services have proxy classes, you will know what’s called where.
      I’ve been using Laravel for quite a long time now and I haven’t had any problem with debugging the code. Although calling non-static methods in a static context is debatable but it also helps developers save some lines of code which I think it’s not a bad thing after all.

      It won’t be misleading as long as it is part of your architecture.

      • http://sputnik.pl Pies

        You can have non-static facade classes and have them use DI like any other class. This has the same benefits without resorting to magic handlers and pseudo-static calls. I stand by my disdain for this article’s core concept :)

        Also, this kind of depends on my IDE’s handling of stuff. If I can still Ctrl+B to get to the source of the call, I don’t mind as much. But I doubt that IDE support for this kind of thing is common.

        • http://infopay50.com Elsie Ventura

          ““I “am “ finally getting 95 Dollars“` an hr,….It’s time to take some action` and you can join it too.It is easy way to get rich`.Three weeks from now you will wish you have started today….

          +++++++++++++>>> Vis!t My Pr0f1le:)“`
          q1q

        • Reza Lavaryan

          Using normal methods in a static context is totally the developer’s choice. You can have a facade class (to simplify an interface) and ignore the “pseudo-static” calls, if you’re not comfortable with them.

          • Melinda Mouton

            Marissa Meyer , Yahoo CEO has gone so far as to Support the practice “Work at home” that I have been doing since last year . In this year till now I have made 58k dollars with my computer , despite the fact that I am a college student . Even newly joined person can make 35h easily and the average increases with time … Look here for details .

            www.NestleUSA.yj.ae
            ➣4

        • JamesDiGioia

          PHPStorm certainly doesn’t support it, and it’s a significant reason I don’t use Laravel’s Facades. All of the services that Facades provide access to can also be made available via the DI container, so unless you’re in a hurry, or building something small, there aren’t a lot of good reasons to use them.

  • Michael Mezger

    I am skeptical if the laravel facades is the right way to go. The biggest problem i see is, that all services are available from EVERY scope. For example: a simple value object shouldnt have access to any service (Of course, the developer of such an value-object should know how to implement it correctly. But when he doesnt have the possibility at all, it should be better). In my opinion the dependencies / services should be passed explicitly and keep all deps under your control and there is a clean interface.

    You could even define your Controller as Services and pass the required services by the DIC and dont need to request services from the dic or use facades. I think that could be a good approach. What do you think?

  • http://DestinyRescue.cf Virgie Calvo

    Is this how it’s possible to earn ninety-seven bucks /hr…? After being un-employed for 6 months, I started freelancing over this web-site and now I cannot be happier. After 4 months on my new job my income is round about dollars 7500/per month working 20hrs a week ..

  • http://DestinyRescue.cf Virgie Calvo

    For web address open my ṖRὀÍLÊ

  • Ds

    Facades, the one (of many) reasons I don’t like Laravel.

    var_dump(debug_backtrace());

    fail!

  • http://www.jaziire.ir مهدی پیشگوی

    بیشتر از اینکه انگیسی زبانها به این احتیاج داشته باشن یه همیچن مقاله ای بهتر بود برای فارسی هم انتشار پیدا میکرد

  • Milan Lesichkov

    Frankly speaking, the way facades are implemented in Laravel is what I call bloatware. It is supposed to be helpful, but in the end increases complexity, makes application had to debug and maintain.

  • JamesDiGioia

    That’s nice, and props to whoever built that tool, but now someone’s spent a bunch of time building a tool solving a problem you could avoid by not using Facades in the first place.

    • Reza Lavaryan

      Well, Laravel facade was not built to solve any architectural problem, but it provides a terse and expressive syntax while keeping the code testable.

      Using facades will be an enjoyable experience, if used responsibly. I’ve been using them for quite some time now, even for enterprise projects but haven’t had any problem debugging my code. The main purpose of Laravel facades are code readability, but not to solve a problem.

      It would be a useful feature, at least for those not using PHPStorm.

      • JamesDiGioia

        You’re right, it was built to cause an architectural problem :trollface:

        But on a serious note, once you get past the “fast prototyping” stage, there aren’t any advantages of use Facades over type-hinting via method injection.

        • Reza Lavaryan

          What architectural problem it is causing? It simply helps you use your container as a service locator.

          However, the goal of this article is not about encouraging developers to prefer this over that. It’s simply a discussion of how things work and how to utilize them elsewhere if needed.

          • JamesDiGioia

            Then use your container as a service locater by typehinting your methods. Laravel will inject your dependencies for you, and everything else works the same way. There’s no reason to hide the service behind a proxy and not-really-static calls that obscure what’s actually going on.

            I appreciate the benefits of using them when you’re just starting out, you’re not sure what your controller or other service methods are going to do, and it easy to just call out to a facade rather than futz with your methods (especially if those methods are taking other, non-service inputs).

            But once you’re past that, and your architecture is stable, going forward, you have a bunch of drawbacks with no benefits compared to other methods of calling those services.

            Edit: I also just noticed you were the author. This isn’t meant as a critique of the article, so much as an argument for when and where Facades should be used, if at all.

  • http://devypt.com Devypt

    Facade Facade Facade Facade WTF, It’s not a good thing that i really want to do or reuse , Laravel make life easier using Facade ! No NO NO , It’s is not easy and it’s just add more complexity.

    I believe that people who stuck with codeigniter just move to laravel.

    • agent_rock

      Kind of throwing the baby out with the bath water. Facades are optional in Laravel. If you don’t like them don’t use them. Sure there are probably many of old CI coders who’ve graduated to Laravel. Good for them. There are also old .NET, ROR and (insert language/framework here) folks coding in Laravel these days simply because it is a powerful and flexible PHP framework that allows for rapid development.

  • Hemant K Kawale

    I am unable to access my vendor classes using facade. I am using laravel 5.3 and php 7.0. I have followed your guide, but when i try to call the class methods like FacadeAlias::classMethod(); I am getting error [Call to undefined method FacadeAlias::classMethod()].

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in PHP, once a week, for free.