serverversion必须显式写在database_url中,doctrine不自动探测mysql版本;漏写或写错会导致dql解析失败、迁移语法错误及make:entity生成异常,且连接池初始化会静默回退。

serverVersion 必须显式写在 DATABASE_URL 里
Doctrine 不会自动探测 MySQL 版本,serverVersion 是强制要求的查询参数,漏掉或写错会导致 DQL 解析失败、迁移报语法错误(比如 JSON_CONTAINS 在 5.7 不可用但 8.0 可用),甚至 make:entity 生成字段类型出错。
它不是 doctrine.yaml 的配置项,也不从 MySQL 服务端读取——只认 DATABASE_URL 查询字符串里的值。
- MySQL 8.0 → 写
?serverVersion=8.0(不能写8.0.33或8) - MySQL 5.7 → 写
?serverVersion=5.7 - MySQL 5.6 → 写
?serverVersion=5.6(Doctrine DBAL 4+ 已不支持,需降级 DBAL 3) - 若用 MariaDB,必须写具体版本号加
mariadb-前缀,如?serverVersion=mariadb-10.11
serverVersion 写错的典型报错现象
不是连不上数据库,而是建表、迁移、甚至 php bin/console make:entity 都会崩:
-
[Syntax Error] line 0, col 72: Error: Expected StateFieldPathExpression, got 'JSON'—— 用了 JSON 类型但serverVersion没设或设成 5.7 -
Unknown database type json requested, Doctrine\DBAL\Types\JsonType not found—— 同上,DBAL 根据版本决定是否启用 JSONType -
Migration failed during Execution. Error: An exception occurred while executing a query: SQLSTATE[42000]: Syntax error or access violation—— 比如迁移里用了CREATE TABLE ... ENGINE=InnoDB ROW_FORMAT=DYNAMIC,但 serverVersion=5.7 时 DBAL 生成了不兼容语句
怎么验证 serverVersion 是否生效
光看 .env 文件不保险,得让 Doctrine 实际加载并输出版本判断逻辑:
- 运行
php bin/console doctrine:dbal:run-sql "SELECT VERSION()",确认返回的是你预期的 MySQL 版本(如8.0.33) - 再执行
php bin/console debug:config doctrine,在输出中找server_version字段,它应等于你 URL 里写的值(如"8.0"),而不是空或"auto" - 如果看到
"server_version": null,说明DATABASE_URL里没带serverVersion参数,或格式错误(比如漏了?、用了&开头)
serverVersion 和连接池配置的耦合关系
启用连接池(pooling: true)时,serverVersion 是硬性前置条件:Doctrine Bundle ≥ 2.10 要求它存在且可解析,否则直接跳过池初始化,静默回退到普通连接。
这意味着,即使你写了完整的 pool: 配置,只要 DATABASE_URL 缺少 serverVersion,php bin/console debug:config doctrine 里也看不到 pool 相关字段。
常见疏忽是:在 Docker Compose 里用 environment: 覆盖 DATABASE_URL,却忘了把 serverVersion 一并带上——本地 .env 有,容器里就没了。











