Связывание синглтона, построенное несколько раз в Laravel - PullRequest
0 голосов
/ 03 ноября 2018

В моем поставщике услуг я связываю класс с синглтоном:

public function register()
{
    $this->app->singleton('ResourceContainer', function($app){
        return new ResourceContainer();
    });
}

В обсуждении Laravel говорится, что этот класс будет разрешен один раз, и тот же объект будет возвращен:

Метод singleton связывает класс или интерфейс в контейнер, который должен быть разрешен только один раз. После разрешения одноэлементной привязки тот же экземпляр объекта будет возвращен при последующих вызовах в контейнер:

Но в моем приложении конструктор ResourceContainer вызывается дважды.

Я хочу вызвать этот экземпляр в моем методе загрузки поставщика услуг:

public function boot()
{
    $resourceContainer = $this->app->make('ResourceContainer');

И я добавляю класс в контроллер:

public function index(ResourceContainer $container, $resource){

Когда я отлаживаю, конструктор ResourceContainer вызывается дважды. Я получаю другой объект в моем контроллере, чем в методе загрузки поставщика услуг.

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Причина в том, что вы запрашиваете разные объекты. Это в основном сводится к этим двум строкам кода:

$resourceContainer = $this->app->make('ResourceContainer');
public function index(ResourceContainer $container) { ... } // simplified

Поскольку у вас, скорее всего, нет класса ResourceContainer, сидящего в глобальном пространстве имен, но, вероятно, где-то вроде App\Services\ResourceContainer, это имя, которое будет запрашиваться из контейнера службы. Таким образом, для подсказки типов класс на самом деле вызовет $this->app->make('App\Services\ResourceContainer') в фоновом режиме, поскольку класс находится в этом пространстве имен.

Поэтому решение довольно простое: зарегистрируйте синглтон под именем класса и измените ручной вызов на make($class). Тип подсказка будет работать из коробки.

public function register()
{
    $this->app->singleton(ResourceContainer::class, function($app) {
        return new ResourceContainer();
    });
}
0 голосов
/ 03 ноября 2018

Вы должны связать полное имя класса вместо:

$this->app->singleton(ResourceContainer::class, function($app){
    return new ResourceContainer();
});

И используйте это так же:

$resourceContainer = $this->app->make(ResourceContainer::class);

Проблема в том, что вы имеете дело с двумя разными строками:

'ResourceContainer'
'Foo\Bar\ResourceContainer'

Когда вы связываете 'ResourceContainer', ...->make('ResourceContainer') правильно разрешит ваш синглтон.

Однако при использовании внедрения зависимости:

public function index(ResourceContainer $container, $resource) {}

Laravel пытается найти полное имя класса 'Foo\Bar\ResourceContainer' из контейнера. Поскольку эта строка не была привязана к контейнеру, Laravel достаточно «умен», чтобы использовать отражение, чтобы автоматически разрешить класс и внедрить новый экземпляр.

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