如何将 Symfony 自动装配与多个实体管理器一起使用

Viv*_*ien 5 entitymanager autowired symfony

我想在使用 2 个不同实体管理器的服务中使用自动装配。如何实现这样的目标?

use Doctrine\ORM\EntityManager;
class TestService
{
    public function __construct(EntityManager $emA, EntityManager $emB)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我的 service.yml 文件的配置如下:

    app.testservice:
        class: App\Services\TestService
        arguments:
            - "@doctrine.orm.default_entity_manager"
            - "@doctrine.orm.secondary_entity_manager"
Run Code Online (Sandbox Code Playgroud)

Cer*_*rad 5

已经发布了两个很好的答案,但我想添加第三个答案以及一些上下文,以帮助选择在给定情况下使用哪种方法。

emix 的答案非常简单,但有点脆弱,因为它依赖于注入正确服务的参数名称。这很好,但您不会从 IDE 获得任何帮助,有时可能会有点尴尬。答案可能应该使用EntityManagerInterface,但这只是一个小问题。

DynlanKas 的答案需要在每个服务中添加一些代码来找到所需的管理器。没关系,但可能有点重复。另一方面,当你事先不知道到底需要哪位经理时,答案是完美的。它允许您根据一些动态信息选择经理。

第三个答案主要基于罗恩的答案,但略有改进。

为每个实体管理器创建一个新类:

namespace App\EntityManager;
use Doctrine\ORM\Decorator\EntityManagerDecorator;
class AEntityManager extends EntityManagerDecorator {}
class BEntityManager extends EntityManagerDecorator {}
Run Code Online (Sandbox Code Playgroud)

不要担心您正在扩展装饰器类。该类具有与“真实”实体管理器相同的接口和相同的功能。您只需要注入所需的管理器:

# config/services.yaml
App\EntityManager\AEntityManager:
    decorates: doctrine.orm.a_entity_manager

App\EntityManager\BEntityManager:
    decorates: doctrine.orm.b_entity_manager
Run Code Online (Sandbox Code Playgroud)

这种方法需要为每个实体管理器创建一个新类以及几行配置,但允许您简单地针对所需的类进行键入提示:

public function __construct(AEntityManager $emA, BEntityManager $emB)
{
}
Run Code Online (Sandbox Code Playgroud)

可以说,这是解决原始问题的最稳健、最标准的方法。


emi*_*mix 2

迪伦的回答违反了德米特定律原则。从 Symfony 3.4 开始就非常简单优雅,满足本地服务绑定

\n\n
services:\n  _defaults:\n    bind:\n      $emA: "@doctrine.orm.default_entity_manager"\n      $emB: "@doctrine.orm.secondary_entity_manager"\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,在您的服务中,自动加载将为您完成艰苦的工作:

\n\n
class TestService\n{\n    public function __construct(EntityManager $emA, EntityManager $emB)\n    {\n        \xe2\x80\xa6\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n