必须显式声明多个entitymanager,仅配置connections无效;需在doctrine.yaml的entity_managers块中为每个manager指定独立connection和mappings,注入时用完整service id(如doctrine.orm.customer_entity_manager),cli命令须加--em=xxx参数。

必须显式声明多个 entity_manager,只配 connections 不生效——这是最常卡住人的地方。
doctrine.yaml 里必须同时配好 connections 和 entity_managers
Doctrine 不会自动为每个 connection 创建对应的 EntityManager。你得在 doctrine.yaml 的 entity_managers 块里逐个定义,且每个 manager 必须明确绑定一个 connection(用 key 名,不是 URL)。
常见错误配置:
- 只加了
dbal.connections.customer,但没在orm.entity_managers下声明customermanager - 写了
customer: {}但漏掉connection: customer,启动时直接报错:The service "doctrine.orm.customer_entity_manager" has a dependency on a non-existent service "doctrine.dbal.customer_connection" - 两个 manager 复用同一组
mappings,导致 Doctrine 加载重复实体类,抛出MappingException: Duplicate class
正确片段示例:
doctrine:
dbal:
connections:
default: { url: '%env(DATABASE_URL)%' }
customer: { url: '%env(DATABASE_CUSTOMER_URL)%' }
orm:
entity_managers:
default:
connection: default
mappings:
App: ~
customer:
connection: customer
mappings:
Customer: ~
注入 EntityManager 时必须指定完整 service ID
容器里不存在泛化的 EntityManagerInterface 实例能自动“切换”到某个库。每个 manager 都是独立 service,ID 格式固定为 doctrine.orm.<name>_entity_manager</name>。
使用方式:
- 构造器注入:
public function __construct(private EntityManagerInterface $customerEm) {}不行;必须写private CustomerEntityManager $em(前提是已用alias或 PHP 8 属性别名映射),或更稳妥地用属性注入:#[Autowire(service: 'doctrine.orm.customer_entity_manager')] - 服务配置中手动注入:
arguments: ['@doctrine.orm.customer_entity_manager'] - 控制器里用
$this->get('doctrine.orm.customer_entity_manager')(不推荐,绕过 DI)
命令行操作必须加 --em=xxx 参数
所有 Doctrine CLI 命令默认只作用于 default manager。想对 customer 库建库、跑迁移、更新 schema,必须显式指定:
php bin/console doctrine:database:create --em=customerphp bin/console doctrine:migrations:migrate --em=customerphp bin/console doctrine:schema:update --force --em=customer
漏掉 --em,命令看似成功,其实完全没碰目标库——尤其是 create 和 drop 类命令,静默失败风险极高。
环境变量 URL 拼接容易引发访问拒绝错误
别用 '%env(resolve:DATABASE_URL)%mydb' 这种拼接方式。一旦 DATABASE_URL 含有查询参数(如 ?serverVersion=8.0),拼接后变成 ...?serverVersion=8.0mydb,URL 解析失败,最终表现为 Access denied for user ... to database。
正确做法是为每个库设独立环境变量:
-
.env中:DATABASE_URL="mysql://app:pass@localhost/default",DATABASE_CUSTOMER_URL="mysql://app:pass@localhost/customer" -
doctrine.yaml中直接引用:url: '%env(DATABASE_CUSTOMER_URL)%'
CI/CD 环境(如 GitLab CI)尤其要注意这点——错误的 URL 拼接会让数据库初始化永远卡在权限报错上,而日志里看不出 URL 已被污染。











