Việc sử dụng nhiều cơ sở dữ liệu cho một dự án không phải là hiếm gặp. Thông thường, khi sử dụng hai cơ sở dữ liệu, các thực thể có thể được tổ chức vào các thư mục cụ thể được khai báo trong cấu hình của bạn. Trong trường hợp này, hệ thống sẽ sử dụng kết nối được cấu hình cho thư mục thực thể. Bạn có thể xem một ví dụ về nhiều kết nối tại đây Symfony 4 / Sonata: quản lý giao diện quản trị đa máy chủ
Giả sử chúng ta muốn chỉ định một cơ sở dữ liệu chỉ đọc (một bản sao) mỗi khi chúng ta sử dụng một thực thể. Sẽ có một số cách tiếp cận khác nhau.
Hãy bắt đầu bằng cách thiết lập nhiều cấu hình.
DATABASE_MASTER=mysql://login:password@db_master.host:3306/db_master?serverVersion=mariadb-10.10.2
DATABASE_SLAVE=mysql://login:password@db_slave.host:3306/db_slave?serverVersion=mariadb-10.10.2
doctrine:
dbal:
default_connection: db_master
types:
json: Sonata\Doctrine\Types\JsonType
connections:
db_master:
url: '%env(resolve:DATABASE_MASTER)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
db_slave:
url: '%env(resolve:DATABASE_SLAVE)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
orm:
auto_generate_proxy_classes: true
default_entity_manager: default
entity_managers:
default:
connection: db_master
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
ApplicationSonataMediaBundle: ~
SonataMediaBundle: ~
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity\'
alias: Main
slave:
connection: db_slave
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: false
mappings:
delef:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: delef
Để chỉ định một kết nối cụ thể, chúng ta có thể chỉnh sửa mã của mình và chỉ đến kết nối của chúng ta cho mỗi yêu cầu Doctrine.
Dưới đây là hai phương pháp để chỉ đến máy chủ phụ của chúng ta cho mỗi yêu cầu:
<?php
namespace App\Repository;
use App\Entity\Whatever;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityRepository;
use Psr\Container\ContainerInterface;
class WhateverRepository extends ServiceEntityRepository
{
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function selectSlave()
{
return $this->container->get('doctrine')
->getManager('slave')
->createQueryBuilder('w')
->andWhere('w.exampleField = :val')
->setParameter('val', $value)
->orderBy('w.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult();
}
}
Hoặc lại:
<?php
namespace App\Repository;
use App\Entity\Whatever;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
class WhateverRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}
public function selectSlave()
{
return $this->registry->
->getManager('slave')
->createQueryBuilder('w')
->andWhere('w.exampleField = :val')
->setParameter('val', $value)
->orderBy('w.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult();
}
}
Nhưng điều này đòi hỏi phải chỉnh sửa tất cả các phương thức của chúng ta từng cái một để chỉ đến kết nối của chúng ta.
Một phương pháp toàn cầu hơn bao gồm việc xác định kết nối của chúng ta trong bộ xây dựng của chúng ta cho toàn bộ kho lưu trữ của chúng ta.
<?php
namespace App\Repository;
use App\Entity\Whatever;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityRepository;
class WhateverRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
$manager = $registry->getManager('slave');
parent::__construct($registry, Whatever::class);
EntityRepository::__construct(
$manager,
$manager->getClassMetadata(Whatever::class)
);
}
public function selectSlave()
{
return $this->createQueryBuilder('w')
->andWhere('w.exampleField = :val')
->setParameter('val', $value)
->orderBy('w.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult();
}
}
Cuối cùng, bạn có thể lựa chọn từ các phương pháp khác nhau tùy theo nhu cầu của ứng dụng của bạn.