Пакет · di

Winter DI

Winter DI — лёгкий PSR-11 контейнер внедрения зависимостей для PHP. Вы описываете то, что нужно классу, типизированными параметрами конструктора, а контейнер сам собирает весь граф объектов — разрешая каждую зависимость по типу, рекурсивно, с тем жизненным циклом (scope), который вы задаёте.

Философия

  • Автовайринг по типам — описывайте зависимости типизированными параметрами; контейнер читает типы через рефлексию и строит всё дерево. Вы перестаёте писать new для сервисов.
  • Явные жизненные циклы — у каждого сервиса есть scope (singleton, request, transient), который решает, будет ли объект общим или собранным заново — а request-scope под Swoole изолируется по корутинам.
  • Конфигурация через атрибуты — классы сами объявляют свой scope и точки внедрения атрибутами (#[Singleton], #[Autowired], …). Никакого центрального XML или массива-конфига.
  • Маленький и стандартный — одна runtime-зависимость (psr/container). Реализует ContainerInterface, поэтому встраивается в любой PSR-11-потребитель.

Ключевые понятия

  • Container — реестр и резолвер. make() разрешает класс, call() вызывает метод с внедрёнными параметрами.
  • Scope — как долго живёт экземпляр: singleton (один на процесс), request (один на запрос / корутину), transient (новый каждый раз).
  • Атрибуты#[Singleton] / #[Request] / #[Transient] задают scope класса; #[Autowired] / #[Inject] отмечают точки внедрения; #[Lazy] откладывает разрешение.
  • ServiceProvider — класс, группирующий связанные привязки (интерфейс → реализация, фабрики, именованные значения) в одном месте.
  • Scanner — проходит по дереву проекта один раз и автоматически регистрирует аннотированные классы через коллекторы вроде DICollector.

Основные возможности

  • Совместимость с PSR-11 — реализует ContainerInterface (get() / has()).
  • Автовайринг конструктора — параметры разрешаются по типу автоматически, рекурсивно.
  • Три scope’аsingleton, request, transient, выбираются атрибутом или привязкой.
  • Внедрение в свойства и методы#[Autowired] / #[Inject] на свойствах; call() разрешает параметры любого callable.
  • Контекстные привязки — фабрики contextual() получают класс-потребитель (например, логгер, названный по классу, который его использует).
  • Ленивое внедрение#[Lazy] внедряет нативный PHP 8.4 proxy, который разрешается при первом обращении, что ломает циклические зависимости (аналог @Lazy из Spring).
  • Сканирование каталогаScanner + DICollector автоматически находят аннотированные классы, с опциональным продакшн-кэшем.
  • Обнаружение циклов — настоящий цикл бросает понятное ContainerException.
  • Swoole-безопасностьrequest-scope использует Coroutine::getContext() для изоляции по корутинам.
  • ReflectionCache — кэш объектов рефлексии на процесс, строится один раз на воркер.

Хорошо подходит для

Любого PHP-приложения, которому нужен автовайринг конструктора и понятные времена жизни сервисов без тяжёлого фреймворк-контейнера — HTTP-контроллеры, CLI-команды и долгоживущие Swoole-воркеры, где важны изоляция по запросам и кэш рефлексии.

Требования

  • PHP ≥ 8.4 (proxy для #[Lazy] использует нативные ленивые объекты PHP 8.4)
  • psr/container ^2.0
  • ext-swooleопционально, только для изоляции request-scope по корутинам в рантайме Swoole

Установка

bash
composer require flytachi/winter-di

Быстрый старт

Отметьте класс scope’ом и запросите его — контейнер сам свяжет его зависимости:

php
use Flytachi\Winter\DI\Container;

$container = Container::init();

$service = $container->make(UserService::class);   // зависимости автовайрятся по типу

Пройдите путь целиком — bootstrap, автообнаружение и первый разрешённый сервис — в Быстром старте.

Исходники и ссылки

Продолжите с Установки и требований, Быстрого старта и Ментальной модели.