Multiple entity managers in Symfony 3.3 seams to not work as service arguments
Asked Answered
E

2

10

I have configured two connections to the database. One connection is called user and other is called client. This is the configuration in the config.yml file:

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

But I am always getting the first entity manager no matter what. This is how I am using entity manager's in services:

# 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']

But no matter what I do, I always get the first entity manager that I have defined under orm->entity_managers settings. For example if configure orm like this:

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

I will always get the client entity manager even if I supply '@doctrine.orm.user_entity_manager' as service argument.

If I configure orm like this:

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

I will always get the user entity manager even if I supply '@doctrine.orm.client_entity_manager' as service argument.

What am I doing wrong here?

Emrich answered 22/11, 2017 at 18:46 Comment(3)
Have you checked bin/console debug:container doctrine.orm.client_entity_manager (or the other) whether the services are registered correctly in the container?Singleminded
Have you tried using @doctrine which gives you a Registry with which you can use getEntityManagerForClass() to retrieve the correct entity manager for any class inside your services?Singleminded
Did you try with a default_entity_manager: user - or whatever you'd like to be your default manager (instead having the default_entity_manager: ~)?Tardiff
K
2

Recently I had a similar issue. The comment of @dbrumann gave me a good clue for resolve it. I used the next approach:

  1. If you use the console command debug:autowiring you will see there is a service aliased as doctrine.

    Doctrine\Common\Persistence\ManagerRegistry alias to doctrine
    
  2. You can get access to that service in your target class by type-hinting, put the name of the service class (or interface) as argument in the constructor of your target class.

  3. Now you can access all the methods of the service in your target class, by using the method getManager() you will get any of your managers:

    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');
    }
    
Kedron answered 22/2, 2018 at 15:46 Comment(0)
U
-1

So you defined a service named DatabaseRepository that exists in two variations. At one point it receives the 'client' entity manager, and at another point it receives 'user' entity manager?

I think it always returns you the 'client' manager most probably because that is the first time the service has been defined for the service container. It does not matter what you define it afterwards in the same .yml code.

Now, there is a big "why" rhetoric question for you. Why didn't you define two service classes, each for particular manager? If you really had to do it that way, that indicates some serious design problems in the remaining code of your Project.

Another suggestion: Do name your classes somewhat more descriptive. An entity manager and repository class certainly do something about a database. Naming classes, properties, variables in a proper way I find to be one of the most challenging part of the work, but it makes our lives easier.

Btw. Avoid passing entire container as service parameter:

arguments: ['@service_container',

because it's too expensive resources wise.

Urita answered 30/11, 2017 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.