Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Жизненный цикл

В долгоживущих процессах — приложениях на RoadRunner, FrankenPHP, фоновых workers или консольных командах, обрабатывающих множество задач — важно контролировать, сколько экземпляров сервиса создаётся и где они живут.

Для этого в библиотеке предусмотрены три типа жизненного цикла. Их можно применять к любым зависимостям: entries, params, alias и autowiring.

Обзор

ТипОписаниеКогда использовать
ScopedОдин экземпляр на контейнерОбработка запросов, пользовательские сессии, изоляция данных
SingletonОдин экземпляр на весь PHP-процессКонфигурация, подключения к БД, кеши
FactoryНовый экземпляр при каждом вызове get()Stateless-сервисы, DTO, временные данные

💡 Классы, указанные в entries, по умолчанию ведут себя как scoped. Указывать их в отдельных разделах не нужно.

Конфигурация

Жизненный цикл определяется в методе definition() класса AbstractProject:

<?php
declare(strict_types=1);

namespace App;

class Project extends \Cekta\DI\AbstractProject
{
    public function definition(): array
    {
        return [
            'entries' => [
                \App\HttpController::class,  // Scoped
            ],
            'singletons' => [
                \App\Database::class,         // Singleton
            ],
            'factories' => [
                \App\HttpRequest::class,      // Factory
            ],
        ];
    }
}

Пример

Рассмотрим, как ведёт себя каждый тип при вызове get() на одном и том же и на разных контейнерах:

<?php
$container1 = new \App\Container();
$container2 = new \App\Container();

$scoped1 = $container1->get(\App\Scoped::class);
$scoped2 = $container1->get(\App\Scoped::class);
// $scoped1 === $scoped2

$singleton1 = $container1->get(\App\Singleton::class);
$singleton2 = $container2->get(\App\Singleton::class);
// $singleton1 === $singleton2

$factory1 = $container1->get(\App\Factory::class);
$factory2 = $container2->get(\App\Factory::class);
// $factory1 !== $factory2
// $factory1 !== $factory2

Сравнение

ТипВнутри одного контейнераМежду разными контейнерамиКогда использовать
ScopedОдин объектРазные объектыОбработка запросов, пользовательские сессии, изоляция данных
SingletonОдин объектОдин объектКонфигурация, подключения к БД, кеши
FactoryРазные объектыРазные объектыStateless-сервисы, DTO, временные данные

Важно

  • Конфликты — один и тот же класс нельзя указать одновременно как Singleton и Factory
  • Производительность — Factory создаёт наибольшую нагрузку, Singleton — наименьшую
  • Потокобезопасность — Singleton должен быть потокобезопасным в многопоточных средах

Полное описание параметров конфигурации — Проект.