Атрибут AutowireIterator
Атрибут AutowireIterator вешается на параметр конструктора или метода
контроллера и внедряет в него итератор сервисов, помеченных заданным тегом.
Первым параметром передаётся имя тега. Вторым параметром можно передать
индекс, по которому сервисы будут отсортированы внутри итератора.
Атрибут избавляет от необходимости вручную настраивать аргумент
с тегом tagged_iterator в конфигурации сервисов.
Синтаксис
#[AutowireIterator(tag, index: index, defaultIndexMethod: method)]
Пример
Давайте создадим интерфейс обработчика и двух его реализаций,
помеченных тегом 'app.handler':
<?php
namespace AppHandler;
interface HandlerInterface
{
public function handle(string $text): string;
}
?>
<?php
namespace AppHandler;
use SymfonyComponentDependencyInjectionAttributeAutoconfigureTag;
#[AutoconfigureTag('app.handler')]
class UpperHandler implements HandlerInterface
{
public function handle(string $text): string
{
return strtoupper($text);
}
}
?>
<?php
namespace AppHandler;
use SymfonyComponentDependencyInjectionAttributeAutoconfigureTag;
#[AutoconfigureTag('app.handler')]
class LowerHandler implements HandlerInterface
{
public function handle(string $text): string
{
return strtolower($text);
}
}
?>
Теперь внедрим итератор этих сервисов в контроллер через атрибут AutowireIterator:
<?php
namespace AppController;
use AppHandlerHandlerInterface;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentDependencyInjectionAttributeAutowireIterator;
use SymfonyComponentHttpFoundationResponse;
class HandlerController extends AbstractController
{
public function __construct(
#[AutowireIterator('app.handler')]
private iterable $handlers,
) {
}
public function index(): Response
{
$res = [];
foreach ($this->handlers as $handler) {
$res[] = $handler->handle('abcde');
}
return new Response(implode(', ', $res));
}
}
?>
Результат выполнения кода:
ABCDE, abcde
Пример
Давайте зададим порядок сервисов в итераторе с помощью индекса. Для этого передадим вторым параметром имя метода, который возвращает индекс:
<?php
namespace AppHandler;
interface HandlerInterface
{
public function handle(string $text): string;
public static function getPriority(): int;
}
?>
<?php
namespace AppHandler;
use SymfonyComponentDependencyInjectionAttributeAutoconfigureTag;
#[AutoconfigureTag('app.handler')]
class UpperHandler implements HandlerInterface
{
public function handle(string $text): string
{
return strtoupper($text);
}
public static function getPriority(): int
{
return 20;
}
}
?>
<?php
namespace AppHandler;
use SymfonyComponentDependencyInjectionAttributeAutoconfigureTag;
#[AutoconfigureTag('app.handler')]
class LowerHandler implements HandlerInterface
{
public function handle(string $text): string
{
return strtolower($text);
}
public static function getPriority(): int
{
return 10;
}
}
?>
Теперь укажем defaultIndexMethod в атрибуте:
<?php
namespace AppController;
use AppHandlerHandlerInterface;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentDependencyInjectionAttributeAutowireIterator;
use SymfonyComponentHttpFoundationResponse;
class HandlerController extends AbstractController
{
public function __construct(
#[AutowireIterator('app.handler', defaultIndexMethod: 'getPriority')]
private iterable $handlers,
) {
}
public function index(): Response
{
$res = [];
foreach ($this->handlers as $handler) {
$res[] = $handler->handle('abcde');
}
return new Response(implode(', ', $res));
}
}
?>
Результат выполнения кода:
abcde, ABCDE
Смотрите также
-
атрибут
Autowire,
который внедряет конкретный сервис или значение -
атрибут
AutowireLocator,
который внедряет локатор сервисов по тегу -
атрибут
TaggedIterator,
который внедряет итератор сервисов по тегу через конфигурацию -
класс
Container,
который хранит и предоставляет сервисы приложения