Несколько менеджеров сущностей в шлейфах Symfony 3.3 не работают как служебные аргументы

Я настроил два подключения к базе данных. Одно соединение называется пользователем, а другое называется клиентом. Это конфигурация в файле config.yml:

doctrine:
    dbal:
        default_connection: client
        connections:
            client:
                driver: pdo_mysql
                host: '%client_database_host%'
                port: '%client_database_port%'
                dbname: '%client_database_name%'
                user: '%client_database_user%'
                password: '%client_database_password%'
                charset: UTF8
                mapping_types:
                    enum: string
            user:
                driver: pdo_mysql
                host: '%user_database_host%'
                port: '%user_database_port%'
                dbname: '%user_database_name%'
                user: '%user_database_user%'
                password: '%user_database_password%'
                charset: UTF8
                mapping_types:
                    enum: string

    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        default_entity_manager: ~
        entity_managers:
            client:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    ProjectModelBundle: ~
                connection: client
            user:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    BaseModelBundle: ~
                    ProjectModelBundle: ~
                connection: user

Но я всегда получаю первый менеджер сущности, несмотря ни на что. Вот как я использую диспетчер сущностей в сервисах:

# BASE
    htec.project_model_bundle.repository.database.client_base:
        class: Project\BaseModelBundle\Repository\Database\DatabaseRepository
        arguments: ['@service_container', '@doctrine.orm.client_entity_manager', '@form.factory']

    htec.project_model_bundle.repository.database.user_base:
        class: Project\BaseModelBundle\Repository\Database\DatabaseRepository
        arguments: ['@service_container', '@doctrine.orm.user_entity_manager', '@form.factory']

Но независимо от того, что я делаю, я всегда получаю первый менеджер сущности, который я определил в настройках orm- > entity_managers. Например, если configure orm выглядит следующим образом:

orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        default_entity_manager: ~
        entity_managers:
            client:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    ProjectModelBundle: ~
                connection: client
            user:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    BaseModelBundle: ~
                    ProjectModelBundle: ~
                connection: user

Я всегда получаю менеджер объектов клиента, даже если я поставлю '@doctrine.orm.user_entity_manager' в качестве аргумента службы.

Если я настрою orm следующим образом:

orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        default_entity_manager: ~
        entity_managers:
            user:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    BaseModelBundle: ~
                    ProjectModelBundle: ~
                connection: user
            client:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    ProjectModelBundle: ~
                connection: client

Я всегда получаю менеджер пользовательских сущностей, даже если я поставлю '@doctrine.orm.client_entity_manager' в качестве аргумента службы.

Что я здесь делаю неправильно?

Ответ 1

Недавно у меня была аналогичная проблема. Комментарий @dbrumann дал мне хороший ключ к его решению. Я использовал следующий подход:

  • Если вы используете консольную команду debug:autowiring, вы увидите, что служба называется псевдонимом.

    Doctrine\Common\Persistence\ManagerRegistry alias to doctrine
    
  • Вы можете получить доступ к этой службе в целевом классе с помощью подсказки типа, поместить имя класса обслуживания (или интерфейса) в качестве аргумента в конструкторе целевого класса.

  • Теперь вы можете получить доступ ко всем методам службы в вашем целевом классе, используя метод getManager(), вы получите любого из ваших менеджеров:

    use Doctrine\Common\Persistence\ManagerRegistry;
    
    $protected $managerRegistry;
    
    public function __construct(ManagerRegistry $managerRegistry)
    {
        $this->managerRegistry = $managerRegistry;
    }
    
    public function foo()
    {
        // asuming your managers names are default and second
        $firstManager = $this->managerRegistry->getManager('default');
        $secondManager = $this->managerRegistry->getManager('second');
    }
    

Ответ 2

Итак, вы определили службу с именем DatabaseRepository, которая существует в двух вариантах. В какой-то момент он получает диспетчер сущностей "клиент", а в другой точке он получает "пользовательский" менеджер сущностей?

Я думаю, что он всегда возвращает вам "клиентский" менеджер, скорее всего, потому что это первый раз, когда служба была определена для контейнера службы. Не имеет значения, что вы потом определяете в том же коде .yml.

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

Другое предложение: Назовите свои классы несколько более наглядными. Администратор сущности и класс репозитория, безусловно, что-то делают с базой данных. Именование классов, свойств, переменных надлежащим образом я считаю одной из самых сложных частей работы, но это облегчает нашу жизнь.

Btw. Избегайте передачи всего контейнера в качестве служебного параметра:

arguments: ['@service_container',

потому что это слишком дорогостоящие ресурсы.