Laravel: разные реализации в экземпляре с контейнером Servcie

#laravel #laravel-5 #dependency-injection #laravel-5.7

#laravel #laravel-5 #внедрение зависимостей #laravel-5.7

Вопрос:

В Laravel, как мне разрешить 2 разные одноэлементные реализации экземпляра с использованием контейнера-сервиса Laravel (https://laravel.com/docs/5.7/container ).

Например, 2 реализации, которые у меня есть для Foo класса, являются:

 $this->app->singleton(Foo::class, function ($app) {
    return new Foo(config('services.foo.apiKey1'));
});
  

и

 $this->app->singleton(Foo::class, function ($app) {
    return new Foo(config('services.foo.apiKey2'));
});
  

Затем мне также нужно как-то это решить:

 $fooV1 = app(Foo::class); // ?
$fooV2 = app(Foo::class); // ?
  

Каков правильный способ написания и разрешения двух разных одноэлементных реализаций экземпляра?

Обновить

Одно из решений, которое я попробовал, заключается в следующем:

 $this->app->singleton(Foo::class, function ($app, $parameters) {
    dump('Creating...'); // For testing only to see is actually a singleton
    $apiKey = $parameters[0] ? config('services.foo.apiKey1') : config('services.foo.apiKey2');
    return new Foo($apiKey);
});
  

а затем разрешить следующим образом:

 $fooV1 = app(Foo::class, [true]);
$fooV2 = app(Foo::class, [false]);
  

Приведенное выше также корректно выводит:

 Creating...
Creating...
  

Поскольку это 2 разных синглета.

Это работает по большей части. Однако аспект singleton не соблюдается. т.Е. при создании одного и того же foo дважды:

 $aV1 = app(Foo::class, [true]);
$bV1 = app(Foo::class, [true]);
  

Выводит:

 Creating...
Creating...
  

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

Ответ №1:

Привязка синглтона

    $this->app->singleton('foo1', function ($app) {
     return new Foo(config('services.foo.apiKey1'));
   });

    $this->app->singleton('foo2', function ($app) {
        return new Foo(config('services.foo.apiKey2'));
     });
  

Вместо передачи Foo::class в первом параметре передайте имя, которое вы будете использовать для разрешения создаваемого вами синглтона

Для решения проблемы выполните следующее

 //a new instance of Foo is created 
$foo1 = $this->app->make('foo1'); 

//the same instance created before is returned
$foo2 = $this->app->make('foo2');
  

Дайте мне знать, если я помог