LAZY SERVICE PROVIDER

Feb 22, 2024 Copy Link

You must be familiar with the Service Providers before embarking on the Deferring approach so, gimme a chance to clarify the providers

 

The key functionality of the providers is bootstrapping (registering) new components to your App such as the `Route` facade class.

 

Let's pretend that we have a `Connection` contract with three classes `DB`, `SQLite`, and `MySQL` and both `SQLite` then `MySQL` classes implement the `Connection` interface whereas the `DB` class accepts a `Connection` type in its constructor, then let's add a new route in the `web.php` file:

 

use App\Classes\DB;
use Illuminate\Support\Facades\Route;

Route::get('defer-binding', [DB::class, 'whateverTheMethodNameIs']);

 

It's all right now, however, we will shocked with an exception when hitting that route because we did not pass the `Connection` type into the `DB`, in such a scenario we must instruct Laravel on how to resolve the `DB` class so, we need to create a new provider for handling that exception:

 

php artisan make:provider DeferBindingServiceProvider

 

In addition, we need to make a bit of change to the `register` method:

 

namespace App\Providers;

use App\Classes\DB;
use App\Classes\SQLite;
use Illuminate\Support\ServiceProvider;

class DeferBindingServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        dump('The `DB` class is gonna be instructed...');

        $this->app->bind(DB::class, fn() => new DB(new SQLite));
    }
}

 

Using the `bind` method we tell Laravel that whenever you find the `DB` class returns an object of a `SQLite` after that, the message will be printed out if you hit the previous route or any route. In reality, you do not need to run that provider at any time but, only in case you call the `DB` class, so you may want to lazily call the provider to enhance the performance therefore let's make another modification:

 

namespace App\Providers;

use App\Classes\DB;
use App\Classes\SQLite;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Support\DeferrableProvider;

class DeferBindingServiceProvider extends ServiceProvider implements DeferrableProvider
{
    ...

    /**
     * Get the services provided by the provider.
     *
     * @return array<int, string>
     */
    public function provides(): array
    {
        return [DB::class];
    }
}

 

You may need to clear the cache using the `cache:clear` command because Laravel caches all the providers according to thier type in the `bootstrap\cache\services.php` file.

 

After the latest change when you knock on any route again, you will find out that the message will be presented only when you hit our new route and this means that we postponed the time of calling and optimized the performance  🚴‍♂️

Share via

Mahmoud Ramadan

Mahmoud Ramadan

Mahmoud is the creator of Digging Code and a contributor to Laravel since 2020.

Most recent

  • How to generate Arabic PDF using TCPDF

    How to generate Arabic PDF using...

    FREE

  • What is SQL Injection

    What is SQL Injection

    FREE

  • Leveraging virtual generated columns in MySQL using Laravel

    Leveraging virtual generated col...

    FREE