How does Laravel defer multiple bindings listed in the same service provider?

I want all my repos to be listed in one service provider, but I don't want all of them downloaded at once ...

Please contact your service provider below:

class RepositoryServiceProvider extends ServiceProvider {

    protected $defer = true;

    public function register()
    {
        $this->app->bind(
            'App\Repositories\Contracts\FooRepository',
            'App\Repositories\SQL\FooSQLRepository');

        $this->app->bind(
            'App\Repositories\Contracts\BarRepository',
            'App\Repositories\SQL\BarSQLRepository');

        // and more to be added later...
    }

    public function provides()
    {

        // Will it defer and load all these at once? Or only the one(s) needed?
        return ['App\Repositories\Contracts\FooRepository',
                'App\Repositories\Contracts\BarRepository'];
    }

}

      

According to the Laravel docs , I can defer registering bindings until needed. But does this work when I have added multiple bindings to one service provider? Specifically, I mean, will it defer and then download everything, or only download the one you want ?

+3


source to share


1 answer


Laravel will register all bindings, even if only one is required. The deferred function actually works quite simply. First, a map of records in provides()

and the actual provider is created:

Illuminate\Foundation\ProviderRepository@compileManifest

if ($instance->isDeferred())
{
    foreach ($instance->provides() as $service)
    {
        $manifest['deferred'][$service] = $provider;
    }
    $manifest['when'][$provider] = $instance->when();
}

      

Then when make()

called in Illuminate\Foundation\Application

...

if (isset($this->deferredServices[$abstract]))
{
    $this->loadDeferredProvider($abstract);
}

      



... and the binding matches one of the deferred providers, it will be here:

Illuminate\Foundation\Application@registerDeferredProvider

$this->register($instance = new $provider($this));

if ( ! $this->booted)
{
    $this->booting(function() use ($instance)
    {
        $this->bootProvider($instance);
    });
}

      

As you might say, the provider is now registered as usual, which means register()

and boot()

. If you think about it, it is not even possible to download one binding from a service provider and not enable others, because it is all done in one way.

+3


source







All Articles