Symfony 3 - EntityManager dependency injection wit

2019-07-25 03:46发布

问题:

I have setup a Custom Authenticator using guard and auto wired the service. This is tested and works fine with just MySQL configured.

I have now specified a second database connection (oracle), but Symfony will now not allow autowiring in my service configuration, because it does not know which database connection to use when injecting EntityManager in to the custom Authenticator class.

Any idea how I can Configure the Dependency Injection to use a specific database connection so I can continue to use AutoWire.

Unable to autowire argument of type "Doctrine\ORM\EntityManager" for the service "user.security.login_form_authenticator". Multiple services exist for this class (doctrine.orm.prism_entity_manager, doctrine.orm.baan_entity_manager).

Here is my Doctrine config in config.yml

doctrine:
    dbal:
        connections:
            prism:
                driver:   pdo_mysql
                host:     "%database_host%"
                port:     "%database_port%"
                dbname:   "%database_name%"
                user:     "%database_user%"
                password: "%database_password%"
                charset:  UTF8
                # if using pdo_sqlite as your database driver:
                #   1. add the path in parameters.yml
                #     e.g. database_path: "%kernel.root_dir%/../var/data/data.sqlite"
                #   2. Uncomment database_path in parameters.yml.dist
                #   3. Uncomment next line:
                #path:     "%database_path%"
            baan:
                driver:   oci8
                host:     "%baan_host%"
                port:     "%baan_port%"
                dbname:   "%baan_db_name%"
                user:     "%baan_user%"
                password: "%baan_password%"
                charset:  AL32UTF8

    orm:
        default_entity_manager: prism
        auto_generate_proxy_classes: "%kernel.debug%"
        entity_managers:
            auto_mapping: true
            prism:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                connection: prism
                mappings:
                    UserBundle:
                        type: annotation

            baan:
                connection: baan
                mappings:
                    BaanBundle:
                        type: annotation

Here is the constructor in my Authenticator class

 private $formFactory;

    private $em;

    private $router;


    public function __construct(FormFactoryInterface $formFactory, EntityManager $em, RouterInterface $router)
    {
        $this->formFactory = $formFactory;
        $this->em = $em;
        $this->router = $router;
    }

回答1:

You can extend Doctrine's EntityManagerDecorator, which implements EntityManagerInterface and accepts an instance of EntityManager in its constructor.

First extend the EntityManagerDecorator class once for each of your connections.

namespace MyBundle\Service\Database;

use Doctrine\ORM\Decorator\EntityManagerDecorator;

class PrismEntityManager extends EntityManagerDecorator {}

class BaanEntityManager extends EntityManagerDecorator {}

Then in your service configuration, you need to manually wire these two services.

MyBundle\Service\Database\PrismEntityManager:
    arguments:
        $wrapped: '@doctrine.orm.prism_entity_manager'

MyBundle\Service\Database\BaanEntityManager:
    arguments:
        $wrapped: '@doctrine.orm.baan_entity_manager'

Now you just have to type-hint for one of these services.

public function __construct(FormFactoryInterface $formFactory, PrismEntityManager $em, RouterInterface $router)
{
    $this->formFactory = $formFactory;
    $this->em = $em;
    $this->router = $router;
}


回答2:

I don't know if i understood your question correctly or not but you can set different configurations for different database connection as below:

dbal:
    default_connection: default
    connections:
        default:
            driver:   pdo_mysql
            host:     "%database_host%"
            port:     "%database_port%"
            dbname:   "%database_name%"
            user:     "%database_user%"
            password: "%database_password%"
            charset:  UTF8
            mapping_types:
            enum: smallint
        custom:
            driver:   pdo_mysql
            host:     '%database_host2%'
            port:     '%database_port2%'
            dbname:   '%database_name2%'
            user:     '%database_user2%'
            password: '%database_password2%'
            charset:  UTF8
            mapping_types:
            enum: smallint
    orm:
        default_entity_manager: default
        auto_generate_proxy_classes: "%kernel.debug%"
        entity_managers:
            auto_mapping: true
            default:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                connection: default
                mappings:
                    EntityBundle:
                        type: annotation
                        alias: DBAlias
            custom:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                connection: custom
                mappings:
                    EntityBundle:
                        type: annotation
                        alias: DBAlias

Now you can passed your custom EntityManager using doctrine.orm.custom_entity_manager.



回答3:

I think, I had the same issue with DBAL Connections as you have with EntityManager. I have solved this issue with some proxy class - described in this answer: https://stackoverflow.com/a/46265170/6357312

Any question let me know.