-
-
Notifications
You must be signed in to change notification settings - Fork 1
Call bind callbacks
Расширения v1.3.0: вызов callable с autowiring, привязка абстракции к реализации, callback после resolve, массовый set() и расширенный API тегов.
Схемы потоков — Архитектура · afterResolving.
| API | Класс / механизм | Назначение |
|---|---|---|
call() |
CallableInvoker |
Вызов функции/метода с autowiring параметров |
bind() |
ServiceAliasResolver + autowire()
|
Интерфейс → класс или id одной строкой |
addDefinitions() |
цикл set()
|
Массовая регистрация из массива |
afterResolving() |
AfterResolvingDispatcher |
Пост-обработка после нового resolve |
getTaggedIds() / getTaggedIterator() / getTaggedLocator()
|
TaggedServiceIterator, TaggedServiceLocator
|
Работа с тегами без eager getTagged()
|
Вызывает функцию, closure, метод объекта или static-метод с autowiring параметров — те же правила, что у конструктора при get():
- PHP attributes
#[Inject]/#[Autowire]на параметре; - autowiring по имени параметра, если включён (
$logger→ id'logger'); - разрешение по типу параметра →
get(FQCN).
Явные значения в $parameters (ключ — имя параметра) переопределяют autowire.
| Форма | Пример |
|---|---|
| Closure / arrow function | static fn (LoggerInterface $l) => $l->info('ok') |
| First-class callable | $handler->handle(...) |
| Массив метод | [self::class, 'factory'] |
| Invokable-объект |
$command с __invoke()
|
| Имя функции |
'strlen' + ['string' => 'abc']
|
$container->enableAutowiring();
$result = $container->call(
static fn (LoggerInterface $logger, string $message) => $logger->info($message),
['message' => 'started'],
);
$handler = new OrderHandler();
$container->call($handler->handle(...), ['orderId' => 42]);Container::call() делегирует ленивому CallableInvoker, который:
- строит
ReflectionFunction/ReflectionMethodдля callable; - для каждого параметра вызывает
MemberResolver::resolveParameter()(тот же путь, что уAutowirer); - выполняет callable через
invokeArgs.
В приложении достаточно Container::call() — CallableInvoker не предназначен для прямого использования.
sequenceDiagram
participant App as Приложение
participant C as Container
participant CI as CallableInvoker
participant MR as MemberResolver
participant AW as Autowirer path
App->>C: call(callable, parameters)
C->>CI: invoke()
loop каждый параметр
CI->>MR: resolveParameter()
MR->>AW: тип / attribute / имя
AW->>C: get(зависимость)
end
CI-->>App: результат вызова
Сокращение для типичной привязки интерфейса / абстракции к реализации:
$concrete |
Поведение |
|---|---|
| instantiable класс |
autowire($concrete) + alias($abstract, $concrete)
|
существующий id (set, autowire, alias) |
только alias($abstract, $concrete)
|
| иначе | ContainerException |
flowchart TD
B[bind abstract, concrete] --> Class{concrete — класс?}
Class -->|instantiable| AW[autowire + alias]
Class -->|id| AL[только alias]
Class -->|иначе| ERR[ContainerException]
$container->enableAutowiring();
$container->bind(LoggerInterface::class, FileLogger::class);
$logger = $container->get(LoggerInterface::class); // FileLogger
$container->set('app.mailer', $mailer);
$container->bind(MailerInterface::class, 'app.mailer');bind() |
alias() |
|
|---|---|---|
| Регистрирует класс | да (autowire для FQCN) |
нет |
| Только переименование id | нет | да |
| Типичный сценарий | интерфейс → реализация | строковый id → FQCN |
Массовый set() — эквивалент последовательных вызовов set($id, $concrete):
$container->addDefinitions([
'config' => $configArray,
'logger' => static fn (Container $c) => new FileLogger($c->get('config')),
'db' => static fn (Container $c) => new PDO($c->get('config')['dsn']),
]);Порядок, приоритет над autowiring и сброс singleton-кэша — как у set().
Удобно для конфигурационных массивов из файла bootstrap или модуля плагина.
Регистрирует callback:
callable(string $id, mixed $instance, ContainerInterface $container): void| Сценарий | Callback |
|---|---|
Первый get($id) — экземпляр создан |
да |
Повторный get($id) из singleton-кэша |
нет |
Каждый make($id) — новый экземпляр |
да (на каждый вызов) |
Несколько callback для одного id выполняются в порядке регистрации.
$container->afterResolving(UserRepository::class, static function (
string $id,
object $repo,
ContainerInterface $c,
): void {
assert($repo instanceof UserRepository);
$c->get('audit')->record('resolved', $id);
});Container::resolveService() после ServiceInstanceResolver::resolve() вызывает AfterResolvingDispatcher::dispatch(), если экземпляр не был взять из singleton-кэша до resolve ($wasCached === false).
sequenceDiagram
participant C as Container
participant SIR as ServiceInstanceResolver
participant ARD as AfterResolvingDispatcher
C->>SIR: resolve(id, singleton)
SIR-->>C: instance
alt новое создание (не из кэша)
C->>ARD: dispatch(id, instance, container)
ARD->>ARD: callback₁…callbackₙ
end
Типичные сценарии: аудит, warmup кэша, регистрация в реестре, логирование времени создания.
См. подробно — Теги и декораторы.
| Метод | Возвращает | Создаёт экземпляры |
|---|---|---|
getTagged($tag) |
id => instance |
да (eager) |
getTaggedIds($tag) |
list<id> |
нет |
getTaggedIterator($tag) |
только значения | да при итерации |
getTaggedLocator($tag) |
has / get / iterate |
при get() / итерации |
- Теги и декораторы
-
Прототипы, alias и lazy —
bind()как альтернатива ручномуalias() - Справочник API
- Autowiring
- Примеры bootstrap
CloudCastle DI · Репозиторий · Packagist · Releases · Discussions · Issues
Исходники Wiki — wiki/ в репозитории (синхронизация через Actions).
- Архитектура
- Быстрый старт
- Сравнение с PHP-DI, Symfony, Pimple — пошагово
- Примеры bootstrap
- Autowiring
- Конфигурация из файлов
- Сканирование классов
- Глобальный реестр
- Теги и декораторы
- call(), bind(), afterResolving
- Прототипы, alias и lazy
- Справочник API
- Фабрики и singleton
- Тестирование
- Тесты безопасности
- Нагрузка и производительность
- Анти-паттерны