Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Події
Інше
Про нас

Чим bind відрізняється від singleton у контейнері?

Обидва кажуть контейнеру, як створювати сервіс. Різниця - у тому, скільки разів це станеться.

bind() створює новий екземпляр щоразу:

$this->app->bind(ReportBuilder::class, function ($app) {
    return new ReportBuilder($app->make(Connection::class));
});

app(ReportBuilder::class) === app(ReportBuilder::class);   // false

singleton() створює один раз і повертає той самий обʼєкт до кінця запиту:

$this->app->singleton(WeatherClient::class, function ($app) {
    return new WeatherClient(config('services.weather.key'));
});

app(WeatherClient::class) === app(WeatherClient::class);   // true

Є ще scoped() - як singleton, але скидається на кожному запиті. Це важливо для Octane, де застосунок живе між запитами й звичайний singleton зберігав би стан довше, ніж треба.

Що обирати. Singleton доречний, коли створення дороге (клієнт із конфігурацією, зʼєднання) або коли стан має бути спільним. bind() - коли обʼєкт накопичує стан і два різних місця не повинні його ділити.

Головна пастка singleton - утримання стану. Сервіс, що накопичує щось усередині, віддасть ці дані наступному, хто його запросить:

class Basket
{
    private array $items = [];

    public function add(Item $item): void
    {
        $this->items[] = $item;   // у singleton лишиться на весь запит
    }
}

Під Octane це вже не «на запит», а між запитами - і дані одного користувача протікають до іншого. Тому в singleton кладуть сервіси без стану, а стан тримають явно.

Докладніше в документації: Сервіс-контейнер

6

Схожі питання