Новое в Symfony 4.3: Индексируемые и помеченные коллекции сервисов

Symfony предоставляет ярлык для внедрения всех служб, помеченных определенным тегом, что является обычной потребностью в некоторых приложениях, поэтому вам не нужно писать пропуск компилятора только для этого. В Symfony 4.3 улучшили это, чтобы позволить доступ к тегированным сервисам по вашему собственному заданному индексу.

В следующем примере сервисы, помеченные app.handler, определяют дополнительный атрибут с именем key. При внедрении их в службу App\HandlerCollection вы можете теперь определить атрибут index_by, чтобы сообщить Symfony, какой индекс следует использовать в ассоциативном массиве, который содержит помеченные службы:

# config/services.yaml
services:
    App\Handler\One:
        tags:
            - { name: 'app.handler', key: 'handler_one' }
    App\Handler\Two:
        tags:
            - { name: 'app.handler', key: 'handler_two' }

    App\HandlerCollection:
        # inject all services tagged with app.handler as first argument
        # and use the value of the 'key' tag attribute to index the services
        arguments: [!tagged { tag: 'app.handler', index_by: 'key' }]

После компиляции контейнера служб, служба HandlerCollection может перебирать обработчики, используя значения, определенные в их ключевых атрибутах:

// src/Handler/HandlerCollection.php
namespace App\Handler;

class HandlerCollection
{
    public function __construct(iterable $handlers)
    {
        $handlers = iterator_to_array($handlers);
        $handlerTwo = $handlers['handler_two'];
        // ...
    }
}

Вместо определения значения индекса в каждом теге службы, вы можете определить это значение в статическом методе getDefaultIndexName() в вашем сервисе. Например, так будет выглядеть предыдущий сервис App\Handler\One:

// src/Handler/One.php
namespace App\Handler;

class One
{
    // ...

    public static function getDefaultIndexName(): string
    {
        return 'handler_one';
    }
}

Имя этого статического метода также можно настроить с помощью атрибута тега default_index_method:

# config/services.yaml
services:
    # ...

    App\HandlerCollection:
        arguments: [!tagged { tag: 'app.handler', default_index_method: 'someCustomMethodName' }]