Як пацювати з багатьма менеджерами сутностей та зʼєднаннями

Дата оновлення перекладу 2022-11-01

Як пацювати з багатьма менеджерами сутностей та зʼєднаннями

Ви можете використовувати багато менеджерів сутностей 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. Ви також визначили два зʼєднання, по одному на кожного менеджера.

Caution

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

Якщо ви використовуєте імʼя, відмінне від default для менеджера сутностей за замовчуванням, вам потрібно буде перевизначити менеджера сутностей за замовчуванням у конфігурації середовища prod і в конфігурації міграцій Doctrine (якщо ви їх використовуєте вы их используете):

1
2
3
4
5
6
# config/packages/prod/doctrine.yaml
doctrine:
    orm:
        default_entity_manager: 'імʼя вашого менеджера сутностей за замовчуванням'

# ...
1
2
3
4
# config/packages/doctrine_migrations.yaml
doctrine_migrations:
    # ...
    em: 'імʼя вашого менеджера сутностей за замовчуванням'

При роботі з багатьма зʼєднаннями для створення ваших баз даних:

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');

        // Цей метод повертає замість цього менеджера сутностей "клієнта"
        $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().