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 🚴♂️