I want all my repositories to be listed in a single service provider, but I don't want them all loaded at once...
Consider the 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 the registration of bindings until needed. But does this work for when I've added multiple bindings in a single service provider? Specifically I mean, will it defer and then load all or load only the one needed?
Laravel will register all bindings, even if only one is needed. The deferred feature actually works pretty simple. First, a map of the entries 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()
is called in Illuminate\Foundation\Application
...
if (isset($this->deferredServices[$abstract]))
{
$this->loadDeferredProvider($abstract);
}
...and the binding matches one of a deferred provider it will end up 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 are able to tell, now the provider is registered as usual which means register()
and boot()
is called. If you think about it, it's not even possible to load one binding from a service provider and not include the other ones, because it's all done in one method.