How to Work with multiple Entity Managers and Connections

You can use multiple Doctrine entity managers or connections in a Symfony application. This is necessary if you are using different databases or even vendors with entirely different sets of entities. In other words, one entity manager that connects to one database will handle some entities while another entity manager that connects to another database might handle the rest. It is also possible to use multiple entity managers to manage a common set of entities, each with their own database connection strings or separate cache configuration.

Symfony アプリケーションで複数の Doctrine エンティティ マネージャーまたは接続を使用できます。これは、異なるデータベースを使用している場合や、エンティティのセットがまったく異なるベンダーを使用している場合に必要です。つまり、1 つのデータベースに接続する 1 つのエンティティ マネージャーが一部のエンティティを処理し、別のデータベースに接続する別のエンティティ マネージャーが残りのエンティティを処理します。複数のエンティティ マネージャーを使用して、それぞれ独自のデータベース接続を持つ共通のエンティティ セットを管理することもできます。文字列または個別のキャッシュ構成。

Note

ノート

Using multiple entity managers is not complicated to configure, but more advanced and not usually required. Be sure you actually need multiple entity managers before adding in this layer of complexity.

複数のエンティティ マネージャーを使用することは、構成が複雑ではありませんが、より高度であり、通常は必要ありません。この複雑なレイヤーを追加する前に、実際に複数エンティティ マネージャーが必要であることを確認してください。

Caution

注意

Entities cannot define associations across different entity managers. If you need that, there are several alternatives that require some custom setup.

エンティティは、異なるエンティティ マネージャ間で関連付けを定義できません。それが必要な場合は、いくつかのカスタム セットアップが必要な代替手段がいくつかあります。

The following configuration code shows how you can configure two entity managers:

次の構成コードは、2 つのエンティティ マネージャーを構成する方法を示しています。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# config/packages/doctrine.yaml
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                # configure these for your database server
                url: '%env(resolve:DATABASE_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
            customer:
                # configure these for your database server
                url: '%env(resolve:DATABASE_CUSTOMER_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                mappings:
                    Main:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Main'
                        prefix: 'App\Entity\Main'
                        alias: Main
            customer:
                connection: customer
                mappings:
                    Customer:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Customer'
                        prefix: 'App\Entity\Customer'
                        alias: Customer

In this case, you've defined two entity managers and called them default and customer. The default entity manager manages entities in the src/Entity/Main directory, while the customer entity manager manages entities in src/Entity/Customer. You've also defined two connections, one for each entity manager, but you are free to define the same connection for both.

この場合、2 つのエンティティ マネージャーを定義し、default と customer と呼びました。デフォルトのエンティティ マネージャは src/Entity/Main ディレクトリのエンティティを管理し、顧客エンティティ マネージャは src/Entity/Customer のエンティティを管理します。また、エンティティ マネージャーごとに 1 つずつ、2 つの接続を定義しましたが、両方に対して同じ接続を自由に定義できます。

Caution

注意

When working with multiple connections and entity managers, you should be explicit about which configuration you want. If you do omit the name of the connection or entity manager, the default (i.e. default) is used.

複数の接続とエンティティ マネージャーを使用する場合は、必要な構成を明示する必要があります。接続またはエンティティ マネージャの名前を省略した場合は、デフォルト (つまり、デフォルト) が使用されます。

If you use a different name than default for the default entity manager, you will need to redefine the default entity manager in the prod environment configuration and in the Doctrine migrations configuration (if you use that):

デフォルトのエンティティ マネージャーにデフォルトとは異なる名前を使用する場合、prod 環境設定と Doctrine 移行設定 (使用する場合) でデフォルトのエンティティ マネージャーを再定義する必要があります。
1
2
3
4
5
6
# config/packages/prod/doctrine.yaml
doctrine:
    orm:
        default_entity_manager: 'your default entity manager name'

# ...
1
2
3
4
# config/packages/doctrine_migrations.yaml
doctrine_migrations:
    # ...
    em: 'your default entity manager name'

When working with multiple connections to create your databases:

複数の接続を使用してデータベースを作成する場合:
1
2
3
4
5
# Play only with "default" connection
$ php bin/console doctrine:database:create

# Play only with "customer" connection
$ php bin/console doctrine:database:create --connection=customer

When working with multiple entity managers to generate migrations:

複数のエンティティ マネージャーと連携して移行を生成する場合:
1
2
3
4
5
6
7
# Play only with "default" mappings
$ php bin/console doctrine:migrations:diff
$ php bin/console doctrine:migrations:migrate

# Play only with "customer" mappings
$ php bin/console doctrine:migrations:diff --em=customer
$ php bin/console doctrine:migrations:migrate --em=customer

If you do omit the entity manager's name when asking for it, the default entity manager (i.e. default) is returned:

エンティティ マネージャの名前を要求するときに省略した場合は、デフォルトのエンティティ マネージャ (つまり、デフォルト) が返されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/Controller/UserController.php
namespace App\Controller;

// ...
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;

class UserController extends AbstractController
{
    public function index(ManagerRegistry $doctrine): Response
    {
        // Both methods return the default entity manager
        $entityManager = $doctrine->getManager();
        $entityManager = $doctrine->getManager('default');

        // This method returns instead the "customer" entity manager
        $customerEntityManager = $doctrine->getManager('customer');

        // ...
    }
}

Entity managers also benefit from autowiring aliases when the framework bundle is used. For example, to inject the customer entity manager, type-hint your method with EntityManagerInterface $customerEntityManager.

エンティティ マネージャーは、フレームワーク バンドルを使用する場合、オートワイヤー エイリアスの恩恵も受けます。たとえば、顧客エンティティ マネージャーを挿入するには、EntityManagerInterface $customerEntityManager を使用してメソッドにヒントを入力します。

You can now use Doctrine like you did before - using the default entity manager to persist and fetch entities that it manages and the customer entity manager to persist and fetch its entities.

以前と同じように Doctrine を使用できるようになりました。デフォルトの entitymanager を使用して管理対象のエンティティを永続化およびフェッチし、customerentity manager を使用してそのエンティティを永続化およびフェッチします。

The same applies to repository calls:

同じことがリポジトリ呼び出しにも当てはまります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// src/Controller/UserController.php
namespace App\Controller;

use AcmeStoreBundle\Entity\Customer;
use AcmeStoreBundle\Entity\Product;
use Doctrine\Persistence\ManagerRegistry;
// ...

class UserController extends AbstractController
{
    public function index(ManagerRegistry $doctrine): Response
    {
        // Retrieves a repository managed by the "default" entity manager
        $products = $doctrine->getRepository(Product::class)->findAll();

        // Explicit way to deal with the "default" entity manager
        $products = $doctrine->getRepository(Product::class, 'default')->findAll();

        // Retrieves a repository managed by the "customer" entity manager
        $customers = $doctrine->getRepository(Customer::class, 'customer')->findAll();

        // ...
    }
}

Caution

注意

One entity can be managed by more than one entity manager. This however results in unexpected behavior when extending from ServiceEntityRepository in your custom repository. The ServiceEntityRepository always uses the configured entity manager for that entity.

1 つのエンティティを複数のエンティティ マネージャで管理できます。ただし、これにより、カスタム リポジトリの ServiceEntityRepository から拡張するときに予期しない動作が発生します。 ServiceEntityRepository は、そのエンティティに対して構成されたエンティティ マネージャーを常に使用します。

In order to fix this situation, extend EntityRepository instead and no longer rely on autowiring:

この状況を修正するには、代わりに EntityRepository を拡張し、オートワイヤーに依存しなくなります。
1
2
3
4
5
6
7
8
9
// src/Repository/CustomerRepository.php
namespace App\Repository;

use Doctrine\ORM\EntityRepository;

class CustomerRepository extends EntityRepository
{
    // ...
}

You should now always fetch this repository using ManagerRegistry::getRepository().

ManagerRegistry::getRepository() を使用して、常にこのリポジトリを取得する必要があります。