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.0ext-swoole— опционально, только для изоляцииrequest-scope по корутинам в рантайме Swoole
Установка
composer require flytachi/winter-diБыстрый старт
Отметьте класс scope’ом и запросите его — контейнер сам свяжет его зависимости:
use Flytachi\Winter\DI\Container;
$container = Container::init();
$service = $container->make(UserService::class); // зависимости автовайрятся по типуПройдите путь целиком — bootstrap, автообнаружение и первый разрешённый сервис — в Быстром старте.
Исходники и ссылки
- GitHub — github.com/flytachi/winter-di
- Packagist — packagist.org/packages/flytachi/winter-di
- Документация — winterframe.net/packages/di
Продолжите с Установки и требований, Быстрого старта и Ментальной модели.