Skip to content

Feature Hooks

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

🪝 Хуки резолвинга (before/after)

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

Контейнер даёт две симметричные точки расширения вокруг создания сервиса:

  • beforeResolving($id, $callback) — колбэк перед созданием нового экземпляра (подготовка окружения, ленивая настройка, аудит запроса);
  • afterResolving($id, $callback) — колбэк после создания сервиса (донастройка, регистрация, логирование).

Туториал — Call-bind-callbacks.

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

BeforeResolvingDispatcher и AfterResolvingDispatcher хранят колбэки по id. Перед фактическим конструированием нового экземпляра контейнер вызывает before-колбэки (передавая id и контейнер); после создания (и применения декораторов) — after-колбэки (передавая созданный объект и контейнер). Флаги hasBeforeResolving/hasAfterResolving гейтят обе проверки — нулевая цена, если хуков нет.

Оба хука срабатывают только при создании нового экземпляра: для повторного get() синглтона из кэша они не вызываются; каждый make() создаёт новый экземпляр и вызывает хуки заново.

// before: подготовка перед созданием (например, аудит или прогрев зависимости)
$c->beforeResolving(ReportBuilder::class, function (string $id, Container $c) {
    $c->get(Clock::class)->freeze(); // детерминированное окружение к моменту сборки
});

// after: донастройка после создания
$c->afterResolving(EventDispatcher::class, function (EventDispatcher $d, Container $c) {
    $d->addSubscriber($c->get(OrderSubscriber::class));
});

$c->afterResolving(Logger::class, fn (Logger $l) => $l->pushHandler(new StreamHandler('php://stderr')));

Плюсы

  • Пост- и пред-обработка без изменения фабрики/класса — расширение сборки в одном месте.
  • Удобно для регистрации подписчиков/хендлеров в общий сервис (after) и для подготовки окружения (before).
  • Гейты hasBeforeResolving/hasAfterResolving — нулевая цена, если хуков нет.

Минусы

  • Скрытая логика инициализации — по фабрике не видно, что вокруг создания навешаны хуки.
  • Порядок нескольких хуков на один id важен и должен быть явным.

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

  • After — для «сборки коллекций»: после создания диспетчера навесить подписчиков.
  • Before — для лёгкой подготовки окружения/аудита перед дорогим конструированием.
  • Держать хуки идемпотентными и без тяжёлых side-effects.

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

  • Прятать в хуке обязательную часть конструирования, которую честнее сделать в фабрике/конструкторе.
  • Многоступенчатая инициализация через цепочку хуков с неочевидным порядком.

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

Контейнер before-аналог after-аналог
PHP-DI нет нет прямого (⚠️ — через фабрику)
Symfony compiler passes (не в рантайме) configurator:, compiler passes
Laravel resolving() afterResolving()
Pimple нет extend() (частично)
Nette нет setup в конфиге

Полноценную пару runtime before/after-хуков на конкретный id дают CloudCastle и (частично) Laravel; остальные закрывают только after-сторону или переносят логику в фазу компиляции.

См. также: Call-bind-callbacks (гайд) · Декораторы.

Clone this wiki locally