我将着手将RDS与主读/写和从属只读设置一起使用。
我已经阅读了有关Doctrine MasterSlaveConnection类型的信息。
但是,我创建了一些端点,希望使用只读副本(大多数GET端点),而有些端点需要写入数据(PUT,PATCH,DELETE端点)。
我也在使用API平台。
在Symfony 4和Doctrine 2中实现此目标的最佳方法是什么?
我将着手将RDS与主读/写和从属只读设置一起使用。
我已经阅读了有关Doctrine MasterSlaveConnection类型的信息。
但是,我创建了一些端点,希望使用只读副本(大多数GET端点),而有些端点需要写入数据(PUT,PATCH,DELETE端点)。
我也在使用API平台。
在Symfony 4和Doctrine 2中实现此目标的最佳方法是什么?
我过去所做的只是使用不同的连接。
类似的东西:
doctrine:
dbal:
default_connection: default
connections:
default:
# This is your Master
url: '%env(DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
slave:
# This would be the slave
url: '%env(DATABASE_SLAVE_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'
prefix: 'App\Entity'
alias: Main
slave:
connection: slave
mappings:
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: Main
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
然后,在您的控制器或业务逻辑中,您可以选择使用默认的实体管理器:
// Controller
$this->getDoctrine()->getEntityManager();
或者您可以获取从属连接:
// Controller
$this->getDoctrine()->getEntityManager('slave');
如果您只需要处理所有请求,而不必为所有请求创建特殊操作,那么最好的选择就是装饰Collection和Item DataProviders来实现学说。
https://symfony.com/doc/current/service_container/service_decoration.html
https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/CollectionDataProvider.php
https://github.com/api-platform/core/blob/master/src/Bridge/Doctrine/Orm/ItemDataProvider.php
因此,基本上,您需要根据$opperationName
更改选择的经理,例如:
if($opperationName === 'GET'){
$manager = $this->managerRegistry->getManager('slave');
} else {
$manager = $this->managerRegistry->getManager();
}
,
您实际上不需要设置多个实体管理器,这也不是可取的,因为处理具有多个实体管理器的一个实体很困难。
使用 Doctrine 2.2,您可以直接从配置中设置从属/副本,而无需额外的实体管理器:
示例:
doctrine:
dbal:
default_connection: default
connections:
default:
dbname: '%env(DATABASE_DBNAME)%'
user: '%env(DATABASE_USER)%'
password: '%env(DATABASE_PASSWORD)%'
host: '%env(DATABASE_HOST)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
slaves:
ro_replica:
dbname: '%env(REPLICA_DBNAME)%'
user: '%env(REPLICA_USER)%'
password: '%env(REPLICA_PASSWORD)%'
host: '%env(REPLICA_HOST)%'
charset: utf8mb4
,
感谢@Chase提供解决方案。你让我开心。尽管它在“开发”环境中对我有效,但切换到“生产”时还是有问题。我收到一个找不到实体的错误。解决方案来自this帖子-感谢@xabbuh。基本上,我必须在doctrine.yml中添加default_entity_manager: name_of_default_em
。这是代码的副本:
# config/packages/prod/doctrine.yaml
doctrine:
orm:
default_entity_manager: BOE <- add this line to let know prod about default em
auto_generate_proxy_classes: false
metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
query_cache_driver:
type: service
id: doctrine.system_cache_provider
result_cache_driver:
type: service
id: doctrine.result_cache_provider
# ...