Coding
With Stef

Laravel Articles
Laravel Videos
General Articles
YouTube Journey Series

9th August 2023  •  Laravel

Reduce database queries with your own Facades

Quite often in our applications we need to run a query to retrieve some data that will be used across many different elements. Facades can be used to make this query once and have the data available for the whole application to use.

Let's take the example of an application that hosts multiple events. Each event has it's own page which contains multiple blade or Livewire components displaying different features.

You might also have a middleware that checks event settings, or other elements also requiring the event data.

Before you know it, you're running the same query 3, 4, 5 or more times across the application during a single page load. This is where a Facade can help.

We will need to create 3 files to get everything working for this, so bear with me and it'll all make sense in the end.

The Facade

In app/Facades create a new PHP class for your facade. I'm going to call mine EventFacade. The class would look like so:

<?php
namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class EventFacade extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'event';
    }
}

As you can see, this file isn't doing a great deal, but is the "glue" that makes everything work.

Essentially, in the getFacadeAccessor method I've defined the name of the service container binding that we want to use. In this case, I've called it event.

You can call this whatever makes sense for your application.

The Service

Next, we need to create a service. This will be the class that actually runs the query and returns the data.

In app/Services create a new PHP class for your service. I'm going to call mine EventService. The class would look like so:

<?php
namespace App\Services;

use App\Models\Contest;
use Illuminate\Support\Facades\Auth;

class EventService
{
    public Event $event;

    public function __construct()
    {
        $this->event = Event::find(1); // Your logic for finding your event goes here
    }

    public function current()
    {
        return $this->event;
    }
}

The __construct is where we run our query - you can adjust to your needs here.

We then have a current method which we will use later to return the current event. You can add any methods you need to this class to access your data in any way you need in your application.

The Service Provider

Finally, we need to create a service provider. This will load our facade, link it to the service and make it available to the application.

In app/Providers create a new PHP class for your service provider. I'm going to call mine EventServiceProvider. The class would look like so:

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Services\EventService;

class EventServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton('event', function () {
            return new EventService();
        });
    }
}

They key part of this is that we've used singleton. Notice I pass event as the first parameter, this must match the accessor that's returned by the Facade.

Using a singleton means that the service will only be instantiated once, and the same instance will be returned each time it is called. This way, we can be sure our query will only ever run once during a page load, no matter how many times we call it.

So, now everything's set up, wherever we need our event data in our application we can simply call:

$event = EventFacade::current();

The first time this is called it will run the query, and every time after that it will return the same instance of the data.

I hope you enjoyed this article. I'm currently working on a project that had this exact requirement, but it took me some digging to figure out how to solve the problem. As always, if you have any feedback, questions or just want to chat about code you can find me on Twitter @CodingWithStef, and on my YouTube channel.

Until next time!

No cookie policy