Symfony 4 - вендор не может найти помеченную автоматическую службу - PullRequest
1 голос
/ 28 марта 2019

Я сделал простой пакет API, который будет (будет) делиться между проектами. Каждый объект / сущность имеет свою собственную конфигурацию, которая говорит, какие поля и как они будут сериализованы (разложены на скалярные значения). Как они будут сериализованы, зависит от выбранного нормализатора. Прямо сейчас есть только один нормализатор по умолчанию, который распознает значение как скалярное, итерируемое или объектное. Пока все работает отлично. Когда вам нужна определенная сериализация, такая как DateTime (где вы не хотите, чтобы декомпозируемый объект подразумевал скалярные значения, а устанавливал формат вывода), вы просто делаете новый нормализатор, который обрабатывает этот объект соответствующим образом.

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

        App\Entity\Example\Category:
            normalizer: asyf.api.service.normalizer.default
            fields:
                title:
                    expose: true
                slug:
                    expose: false
                items:
                    orderBy:
                        title:
                            priority: 1
                            direction: DESC
                    limit: 2
                    expose: true

Нормализаторы помечены как "asyf.api.normalizer". Поскольку он создан как пакет поставщика, я использовал его расширение для внедрения зависимостей, чтобы загружать службы по тегам и внедрять их в службу NormalizersManager, которая хранит их и может восстановить их по имени ключа

class AsyfApiExtension extends Extension
{
    /**
     * @param array $configs
     * @param ContainerBuilder $container
     *
     * @throws \Exception
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
        $loader->load('services.yml');

        $container->setParameter('asyf_api', $config);

        $normalizerManagerDefinition = $container->findDefinition('asyf.api.service.normalizers_manager');
        $defaultNormalizerId = 'asyf.api.service.normalizer.default';
        $defaultNormalizerReference = new Reference($defaultNormalizerId);
        $normalizerManagerDefinition->addMethodCall('add', array($defaultNormalizerId, $defaultNormalizerReference));

        $taggedNormalizers = $container->findTaggedServiceIds('asyf.api.normalizer');

        foreach ($taggedNormalizers as $id => $tags) {
            $normalizerReference = new Reference($id);
            $normalizerManagerDefinition->addMethodCall('add', array($id, $normalizerReference));
        }
    }
}

Теперь к проблеме: Этот контейнер в AsyfApiExtension :: load не может видеть помеченные сервисы вне своей области. Он просто видит сервисы, определенные в этом пакете. Поэтому, когда я создаю новый нормализатор с автопроводкой и регистрирую его в config / services.yaml с тегом, пакет поставщика не видит его и не добавляется в службу NormalizersManager, поэтому его нельзя использовать.

    App\Service\Search\Normalizer\SearchResultNormalizer:
        public: true
        tags:
            - { name: 'asyf.api.normalizer' }

Чтобы решить эту проблему, я могу добавить ее вручную, но затем теряю мысль об автоматической настройке. Есть ли способ сделать новые нормализаторы с автоматической проводной связью доступными в расширении поставщика? Спасибо за любые идеи

1 Ответ

2 голосов
/ 28 марта 2019

Я нашел решение, мне нужно немного переписать код, но вот оно:

    asyf.api.service.normalizers_manager:
        class: App\Service\Search\NormalizersManager
        arguments: [!tagged asyf.api.normalizer]

!tagged asyf.api.normalizer добавляет набор служб с тегом asyf.api.normalizer

...