指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
symfony7之doctrine.yaml配置
doctrine:
    dbal:
        connections:
            default: # 主数据库连接
                server_version: '8.0'
                url: '%env(resolve:DATABASE_PRIMARY_URL)%'
                driver: pdo_mysql
                charset: utf8mb4
                default_table_options:
                    collate: utf8mb4_unicode_ci
                mapping_types:
                    enum: string
                schema_filter: ~^(?!(messenger_messages|migration_versions)$)~
                replicas: # 让 SELECT 语句自动走 secondary(从库)
                    secondary:
                        url: '%env(resolve:DATABASE_SECONDARY_URL)%'
            secondary: # 额外手动指定的从库连接
                url: '%env(resolve:DATABASE_SECONDARY_URL)%'
        default_connection: default

    orm:
        auto_generate_proxy_classes: true
        enable_lazy_ghost_objects: true

        default_entity_manager: default # 默认 entity_manager
        entity_managers:
            default:
                connection: default # 绑定到 dbal.connections.default
                mappings:
                    App:
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: App
                    tree:
                        type: attribute # or annotation or xml
                        alias: Gedmo
                        prefix: Gedmo\Tree\Entity
                        dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Tree/Entity"
                # add qinhongpub databases so doctrine can ignore them while executing 'doctrine:migration:diff' command
                schema_ignore_classes:
                    - App\Entity\qinhongpub\User
                    - App\Entity\qinhongpub\Continent
                    - App\Entity\qinhongpub\Country
                    - App\Entity\qinhongpub\UserJobtype
                    - App\Entity\qinhongpub\UserMultipleEmail
                    - App\Entity\qinhongpub\UserTitle
                    - App\Entity\qinhongpub\UserWorkplace
                    - App\Entity\qinhongpub\EmailUserRel
                    - App\Entity\qinhongpub\ExchangeRate
                dql:
                    string_functions:
                        concat_ws: DoctrineExtensions\Query\Mysql\ConcatWs

            secondary:
                connection: secondary # 绑定 `dbal.connections.secondary`
                mappings:
                    App:
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: App
                    tree:
                        type: attribute # or annotation or xml
                        alias: Gedmo
                        prefix: Gedmo\Tree\Entity
                        dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Tree/Entity"
                dql:
                    string_functions:
                        concat_ws: DoctrineExtensions\Query\Mysql\ConcatWs
使用
先在 service.yaml下配置binbd参数
bind:
    $em: "@doctrine.orm.default_entity_manager" # _entity_manager 是一个固定的格式,通常是为了与 Doctrine 的内部约定保持一致。Doctrine 会根据配置的 entity_managers 部分的名称自动生成这些实体管理器的服务名称。如果您定义了多个实体管理器(如 default、secondary、third),Doctrine 会为每个管理器生成对应的服务名称,后缀 _entity_manager 是固定的。
    $emSlave: "@doctrine.orm.secondary_entity_manager" # _entity_manager 是一个固定的格式,通常是为了与 Doctrine 的内部约定保持一致。Doctrine 会根据配置的 entity_managers 部分的名称自动生成这些实体管理器的服务名称。如果您定义了多个实体管理器(如 default、secondary、third),Doctrine 会为每个管理器生成对应的服务名称,后缀 _entity_manager 是固定的。
    
例子:
use Doctrine\ORM\EntityManagerInterface;

class MyService
{
    private EntityManagerInterface $em;
    private EntityManagerInterface $emSlave;

    public function __construct(EntityManagerInterface $em, EntityManagerInterface $emSlave)
    {
        $this->em = $em;
        $this->emSlave = $emSlave;
    }

    public function fetchData()
    {
        // 从主数据库查询
        $data = $this->em->getRepository(SomeEntity::class)->findAll();

        // 从从数据库查询
        $dataSlave = $this->emSlave->getRepository(SomeEntity::class)->findAll();

        return [$data, $dataSlave];
    }
}


// 手动切换数据库连接
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;

class YourService
{
    public function __construct(
        private readonly EntityManagerInterface $em,
        private readonly ManagerRegistry $doctrine, // 允许手动获取不同的 EntityManager
    ) {
    }

    public function getUserFromSlave(int $id)
    {
        $emSlave = $this->doctrine->getManager('secondary'); // 获取 secondary EntityManager
        return $emSlave->getRepository(User::class)->find($id);
    }
}
分析
dbal(Database Abstraction Layer[数据库抽象层]) 和 orm(Object-Relational Mapper[ORM 映射层]) 是两个不同的部分,它们各自负责不同的任务,但相互配合使用。

dbal:
作用:
负责管理数据库连接
处理SQL 语句的执行
支持多个数据库连接
提供事务管理

上面配置分析:
dbal.connections.default
这是主数据库连接
replicas 让 SELECT 查询可以自动走 secondary (所以当前的配置,,默认就通过replicas实现了主从数据库操作)

dbal.connections.secondary
这是额外定义的从库连接
主要用于手动切换 EntityManager 使用

default_connection: default
默认情况下,Doctrine 会使用 default 连接
👉 结论:dbal 只管数据库连接,不涉及 ORM 映射

orm:
作用:
负责实体(Entity)和数据库表的映射
让你用 PHP 对象 而不是 SQL 语句操作数据库
需要 EntityManager 来管理数据库操作
支持 多个 EntityManager,每个 EntityManager 可以绑定不同的数据库连接

上面配置分析:
default_entity_manager: default
默认 EntityManager 绑定 dbal.connections.default

entity_managers.default.connection: default
这个 EntityManager 绑定到 default(主数据库)

entity_managers.secondary.connection: secondary
这个 EntityManager 绑定到 secondary(从数据库)

最终效果:
默认 ORM 查询会自动使用 dbal.default
如果是 SELECT 语句,Doctrine 会自动切换到 replicas.secondary
如果是 INSERT/UPDATE/DELETE 语句,Doctrine 仍然使用 dbal.default(主库)
如果手动指定 orm.entity_managers.secondary,那么所有操作都走 dbal.connections.secondary