Aug 22, 2017 | laravel, laravel 5.4, Facades

Real-time (automatic) Facades in Laravel 5.4

Series

This is a series of posts on New Features in Laravel 5.4.

!
Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.

Laravel 5.4 introduced a new feature called “real-time facades”, which provide the convenience of facades, defined real-time instead of in classes. Taylor tweeted about it, but I wanted to explain what they are and how they work.

A quick introduction to facades in Laravel

Already know how facades work? Skip to what’s new.

If you’re not familiar with facades in Laravel, they’re shortcut classes that provide static access to non-static methods on service classes bound to Laravel’s container. Phew, that’s a mouthful; let’s take a look at some real code.

For instance, if I want get something from the session, here’s one way to do it in Laravel:

<?php

namespace App\Http\Controllers;

use Illuminate\Session\SessionManager;

class ThingController extends Controller
{
    protected $session;

    public function __construct(SessionManager $session)
    {
        $this->session = $session;
    }

    public function doThing()
    {
        $importantValue = $this->session->get('important');
    }
}

… or in a view:

Your user ID is: {{ app('Illuminate\Session\SessionManager')->get('important') }}

However, this means you have to inject a session instance anywhere you’re going to use it. This isn’t a big issue, but especially in views and sometimes controllers (especially before controllers were namespaced), this hasn’t always the most convenient. The app() helper also makes it easier, as you can see in the view example. But facades make that even easier:

<?php

namespace App\Http\Controllers;


use Illuminate\Support\Facades\Session;

public function ThingController extends Controller
{
    public function doThing()
    {
        $importantValue = Session::get('important');
    }
}

… or in a view:

Your user ID is: {{ Session::get('important') }}

The facade works like this:

class Session extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'session';
    }
}

This is telling the container this: “When I use a static method on the Session facade, call it on an instance of app('session')”. The facade functionality pulls an instance out of the container and calls the method directly on that.

Good? Good. Let’s cover what a real-time facade is.

Introducing real-time facades

Real-time facades let you create your own facades on the fly. Instead of having to create a facade class like the Session facade class I referenced above, you can use a class as its own facade by adding Facades\ to the beginning of its own namespace.

Let’s say I have a class called Charts that has a burndown() method:

<?php

namespace App;

class Charts
{
    protected $dep;

    public function __construct(SomeDependency $dep)
    {
        $this->dep = $dep;
    }

    public function burndown()
    {
        return 'stuff here' . $this->dep->stuff();
    }
}

There’s nothing special about this class. Here’s how we would normally use it in a view:

<h2>Burndown</h2>
{{ app(App\Charts::class)->burndown() }}

Now, let’s make it a facade, just by changing the namespace:

<h2>Burndown</h2>
{{ Facades\App\Charts::burndown() }}

Or, in a class, from this:

<?php

namespace App\Stuff;

use App\Charts;

class ThingDoer
{
    private $charts;

    public function __construct(Charts $charts)
    {
        $this->charts = $charts;
    }

    public function doThing()
    {
        $this->charts->burndown();
    }
}

to this:

<?php

namespace App\Stuff;

use Facades\App\Charts;

class ThingDoer
{
    public function doThing()
    {
        Charts::burndown();
    }
}

Post::conclude()

That’s all. Just a quick and simple way to create a facade on the fly. One more tool in your terseness arsenal.

You might be asking yourself, "why all the fuss for something so simple?" In terms of its terseness, it definitely has a lot of value in some contexts and negligible impact in others. What if I told you, though, that you could use real-time façades to make your code more testable?

Taylor wrote a great post explaining how he uses real-time facades in his Forge code, and how it's now more testable as a result.


Comments? I'm @stauffermatt on Twitter


Tags: laravel  •  laravel 5.4  •  Facades


This is part of a series of posts on New Features in Laravel 5.4:

  1. Feb 3, 2017 | laravel 5.4, Dusk
  2. Feb 8, 2017 | laravel, laravel 5.4, mix
  3. Aug 22, 2017 | laravel, laravel 5.4, Facades

Subscribe

For quick links to fresh content, and for more thoughts that don't make it to the blog.