Как Laravel откладывает несколько привязок, перечисленных в одном поставщике услуг?

Я хочу, чтобы все мои репозитории были перечислены в одном поставщике услуг, но я не хочу, чтобы все они загружались одновременно...

Рассмотрим поставщика услуг ниже:

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'];
    }

}

Согласно документам Laravel, я могу отложить регистрацию привязок до тех пор, пока это не потребуется. Но работает ли это, когда я добавил несколько привязок в одном поставщике услуг? В частности, я имею в виду, будет ли он отложить и затем загрузить все или загрузить только тот, который нужен?

1 ответ

Решение

Laravel зарегистрирует все привязки, даже если нужна только одна. Отложенная функция на самом деле работает довольно просто. Во-первых, карта записей в provides() и фактический поставщик создан:

Illuminate\Foundation\ProviderRepository@compileManifest

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

Тогда, когда make() называется в Illuminate\Foundation\Application...

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

... и привязка соответствует одному из отложенных провайдеров, это будет в конечном итоге здесь:

Illuminate\Foundation\Application@registerDeferredProvider

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

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

Как вы могли бы сказать, теперь провайдер зарегистрирован как обычно, что означает register() а также boot() называется. Если вы подумаете об этом, даже невозможно загрузить одну привязку от поставщика услуг и не включать другие, потому что все это делается одним способом.

Другие вопросы по тегам