Пакет · di

Scope’ы

Scope определяет, как долго живёт разрешённый экземпляр и является ли он общим. Их три: singleton, transient и request. Класс выбирает один атрибутом или привязкой; по умолчанию — transient.

Три scope’а

Scope Идентичность Кэшируется Задаётся
singleton один на процесс да, после первого make() #[Singleton] · singleton()
transient новый при каждом разрешении нет #[Transient] · bind() · transient() · (по умолчанию)
request один на запрос / корутину на запрос #[Request] · request()

singleton

Создаётся при первом make(), кэшируется в контейнере, возвращается при каждом последующем вызове.

Для stateless-сервисов — репозиториев, фабрик, пулов соединений, читателей конфигурации. Избегать для классов с пер-запросным состоянием; оно утечёт между запросами под Swoole.

transient

Без кэширования — каждый make() / внедрение возвращает свежий объект. Это вариант по умолчанию, когда у класса нет scope-атрибута и ручной привязки.

Для объектов с состоянием, которые не должны быть общими — билдеров запросов, form-объектов, DTO, unit of work.

request

Один экземпляр на HTTP-запрос, в зависимости от рантайма:

Рантайм Поведение
Swoole Хранится в Coroutine::getContext()['__di'] — полностью изолирован по корутинам. Каждый параллельный запрос получает свой экземпляр, очищается по завершении корутины.
FPM Эквивалентно singleton — один запрос = один процесс, поэтому кэш на уровне процесса корректен.
CLI Эквивалентно singleton — одна команда = один процесс.

request-scope — единственное место, где важен ext-swoole; см. Request-scope и Swoole.

Приоритет

Ручная регистрация всегда переопределяет scope-атрибут класса — побеждает последняя привязка.

php
#[Singleton]
class UserService {}

// Переопределить в transient для конкретного контекста (напр. тестов)
$c->transient(UserService::class);
// → UserService теперь transient, независимо от #[Singleton]

Overrides полностью обходят кэш

make($abstract, $overrides) с непустым массивом $overrides всегда строит свежий экземпляр и не читает и не пишет кэш singleton/request — независимо от scope. Используйте make() без overrides, чтобы получить общий экземпляр.

Матрица безопасности Swoole

Никогда не помещайте изменяемые пер-запросные данные в singleton под Swoole — они утекут между параллельными запросами, разделяющими память воркера.

Тип класса Рекомендуемый scope
Пул соединений с БД singleton
Репозиторий (stateless) singleton
Читатель конфигурации singleton
Контекст авторизации request
Текущий пользователь request
Unit of work request
Билдер запросов transient
DTO / value object transient
Form-объект transient

Связанное