Non è insolito avere più database per un singolo progetto. Normalmente, quando si utilizzano due database, le entità possono essere organizzate in specifiche cartelle che sono dichiarate nella tua configurazione. In questo caso, il sistema utilizzerà la connessione configurata per la directory dell'entità. Puoi vedere un esempio di connessioni multiple qui Symfony 4 / Sonata: gestire un'interfaccia di amministrazione multi-server
Supponiamo che vogliamo puntare a un database in sola lettura (una replica) ogni volta che utilizziamo un'entità. Ci sarebbero diversi modi di procedere.
Iniziamo impostando più configurazioni.
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
Per puntare a una connessione specifica, potremmo modificare il
nostro codice e puntare alla nostra connessione per ogni richiesta
Doctrine.
Ecco già due metodi per puntare al nostro server
slave per ogni richiesta:
<?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();
}
}
O ancora:
<?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();
}
}
Ma ciò implica modificare tutti i nostri metodi uno per uno per
puntare alla nostra connessione.
Un metodo più globale
consiste nel definire la nostra connessione nel nostro costruttore
per l'intero repository.
<?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();
}
}
Alla fine, puoi scegliere tra i diversi metodi disponibili
secondo le esigenze della tua applicazione.