Как работать с множеством менеджеров сущностей и соединениями

Дата обновления перевода 2022-01-09

Как работать с множеством менеджеров сущностей и соединениями

Вы можете использовать множество менеджеров сущностей Doctrine или соединений в приложении Symfony. Это необходимо, если вы используете разные базы данных, или даже поставщиков с абсолютно разными наборами сущностей. Другими словами, один менеджер сущностей, который соединяется с одной базой данных, будет управлять некоторыми сущностями, в то время как другой менеджер сущностей, который соединяется с другой базой данных, может управлять всеми остальными.

Note

Использовать множество менеджеров сушностей достаточно просто, но это более продвинутый уровень, и обычно не требуется. Убедитесь в том, что вам на самм деле нужно множество менеджеров сушностей перед тем, как добавлять этот уровень сложности.

Caution

Сущности не могут определять ассоциации по разным менеджерам сущностей. Если вам нужно это, существует несколько альтернатив, которые требуют особенной установки.

Следующий код конфигурации показывает, как вы можете сконфигурироваь два менеджера сущностей:

  • YAML
  • XML
  • 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:
                # сконфигурируйте их для вашего сервера БД
                url: '%env(resolve:DATABASE_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
            customer:
                # сконфигурируйте их для вашего сервера БД
                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

В этом случае, вы определили два менеджера сущностей и назвали их default и customer. Менеджер сущностей default управляет сущностями в каталоге src/Entity/Main, а менеджер сущностей customer - в src/Entity/Customer. Вы также определили два соединения, по одному для каждого менеджера.

Note

При работе со множественными соединениями и несколькими менеджерами сущностей, вы должны явно указывать, какую конфигурацию вы хотите. Если вы упустите имя соединения или менеджера сущностей, будет использовано имя по умолчанию (т.е. default).

Если вы используете имя, отличное от default для менеджера сущностей по умолчанию, вам нужно будет переопределить менеджера сущностей по умолчанию в конфгигурации окружения 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'

При работе с множеством соединений, для создания ваших DB:

1
2
3
4
5
# Играть только с соединением "default"
$ php bin/console doctrine:database:create

# Играть только с соединением "customer"
$ php bin/console doctrine:database:create --connection=customer

При работе с множеством менеджеров сущностей для генерирования миграций.

1
2
3
4
5
6
7
# Играть только с отображениями "default"
$ php bin/console doctrine:migrations:diff
$ php bin/console doctrine:migrations:migrate

# Играть только с отображениями "customer"
$ php bin/console doctrine:migrations:diff --em=customer
$ php bin/console doctrine:migrations:migrate --em=customer

Если вы упустите имя менеджера сущностей при его запросе, будет возвращён менеджер сущностей по умолчанию (т.е. default):

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
    {
        // Оба метода возвращают менеджера сущностей по умолчанию
        $entityManager = $doctrine->getManager();
        $entityManager = $doctrine->getManager('default');

        // Этот метод возвращается вместо менеджера сущностей "customer"
        $customerEntityManager = $doctrine->getManager('customer');

        // ...
    }
}

Менеджеры сущностей также получают преимущества от псевдонимов автомонтирования , когда используется пакет фреймворка . Например, чтобы внедрить менеджра сущностей customer, введите в ваш метод подсказку EntityManagerInterface $customerEntityManager.

Теперь вы можете использовать Doctrine так же, как и раньше - путём использования менеджера сущностей default для сохранения и возврата сущностей, которыми он управляет, и менеджера сущностей customer для сохранения и возврате его сущностей.

То же самое применяется к вызовам хранилиша:

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
    {
        // Извлекает хранилище, управляемое менеджером сущностей "default"
        $products = $doctrine->getRepository(Product::class)->findAll();

        // Ясный способ разобраться с менеджером сущностей "default"
        $products = $doctrine->getRepository(Product::class, 'default')->findAll();

        // Извлекает хранилище, управляемое менеджером сущностей "customer"
        $customers = $doctrine->getRepository(Customer::class, 'customer')->findAll();

        // ...
    }
}

Caution

Одна сущность может управляться более, чем одним менеджером сущностей. Это, однако, приводит к неожиданным результатом при расширении из ServiceEntityRepository в вашем пользовательском хранилище. ServiceEntityRepository всегда использует сконфигурированного менеджера сущностей для этой сущности.

Для того, чтобы исправить эту ситуацию, взамен расширьте 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
{
    // ...
}

Теперь вы должны всегда извлекать это хранилище, используя ManagerRegistry::getRepository().