Reputation: 6769
I'm following the documentation here https://symfony.com/doc/current/reference/configuration/doctrine.html about setting up alternative database connections for the purpose of read replication. For reference I'm using AWS Aurora PostgreSQL with end points for primary and read only.
I've set the this for my doctrine.yaml
doctrine:
dbal:
default_connection: default
connections:
default:
url: '%env(resolve:DATABASE_URL)%'
read:
url: '%env(resolve:READ_URL)%'
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
dql:
datetime_functions:
date_trunc: App\DoctrineExtensions\DateTrunc
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
read:
connection: read
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: false
dql:
datetime_functions:
date_trunc: App\DoctrineExtensions\DateTrunc
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
auto_generate_proxy_classes: true
And calling the read only orm as:
$user = $this->getDoctrine()->getRepository(User::class, 'read')->findOneBy(['email' => $payload['email']]);
as an example.
If I call this it still goes to the default database. If I misname it Symfony throws an exception as expected so I can confirm the config is being picked up and loading correctly.
How is my config or call incorrect that it's still requesting from the default
database connection or is there any better way to define read replicas for the data connection? I haven't found any current documentation for it.
Upvotes: 0
Views: 1868
Reputation: 3324
According to this:
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. In order to fix this situation, extend EntityRepository instead and no longer rely on autowiring:
So you should make sure your repository extends EntityRepository
instead of ServiceEntityRepository
.
Then you should now always fetch this repository using ManagerRegistry::getRepository()
.
So basically this would work since $this->getDoctrine()
return an instance of ManagerRegistry
.
$user = $this->getDoctrine()->getRepository(User::class, 'read')->findOneBy(['email' => $payload['email']]);
The downside is you will not be able to use autowiring for the repository itself.
So this would not work unless you pass that repository manually.
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
Upvotes: 1