Skip to content

Feature Scoped

github-actions[bot] edited this page Jul 8, 2026 · 1 revision

🔲 Scoped-сервисы

← Возможности · Главная · Сравнение

Scoped-сервис — singleton в пределах scope и transient вне его. Один экземпляр на запрос/задачу, новый — на следующую. Туториал — Scopes.

Принцип работы

scoped($id, $concrete) регистрирует сервис как scope-зависимый. beginScope() открывает область (вложенные — стеком, LIFO), endScope() закрывает и сбрасывает созданные в ней scoped-экземпляры. Внутри активного scope get($id) возвращает один и тот же экземпляр; вне scope или в новом scope — создаётся заново. inScope(), isScoped(), scopeDepth() — интроспекция. Реализация (ContainerScopeSupport) не влияет на обычный singleton-кэш и гейтится флагом hasScoped (нулевая цена, если scoped не используются).

$c->scoped(RequestContext::class, fn () => new RequestContext());

$c->beginScope();
$a = $c->get(RequestContext::class);
$b = $c->get(RequestContext::class);
$a === $b;              // true — один на scope
$c->endScope();

$c->beginScope();
$c2 = $c->get(RequestContext::class);
$c2 === $a;             // false — новый scope, новый экземпляр
$c->endScope();

Плюсы

  • Изоляция состояния запроса/задачи в долгоживущих процессах (worker, Swoole, RoadRunner): один контекст на итерацию, без утечек между запросами.
  • Вложенные scope-ы (LIFO) для под-задач.
  • Нулевой overhead, если scoped-сервисы не заведены.

Минусы

  • Нужно дисциплинированно парой beginScope()/endScope() обрамлять единицу работы.
  • Забытый endScope() = удержание состояния между итерациями (утечка).

✅ Рекомендуется

  • Оборачивать обработку каждого запроса/сообщения в beginScope()endScope() (желательно через try/finally).
  • Хранить в scoped-сервисах контекст запроса (текущий пользователь, correlation-id), а не в глобальных singleton.

❌ Антипаттерны

  • Держать состояние запроса в обычном singleton в долгоживущем процессе — утечёт в следующий запрос (безопасность!).
  • Открывать scope и не закрывать его в finally при исключении.

Аналоги в других контейнерах

Контейнер Аналог
PHP-DI scope устарел/ограничен (⚠️)
Symfony request scope / kernel.reset (эталон в fullstack)
Laravel scoped() binding (per-request в Octane)
Pimple нет (❌)
Nette ограниченно (⚠️)

CloudCastle, Symfony, Laravel — полноценные scoped-сервисы.

См. также: Scopes (гайд) · Прототипы.

Clone this wiki locally