必须在doctrine.yaml中显式配置charset和default_table_options,且serverVersion需与MySQL实际版本一致,否则DATABASE_URL中的charset参数无效;还需手动ALTER已有表。

DATABASE_URL 里加 charset 参数没用
Doctrine 默认从 DATABASE_URL 解析连接参数,但 charset 不是标准 URL 查询参数,直接写成 ?charset=utf8mb4 会被忽略。Symfony 8.0(基于 Doctrine DBAL 4.x)要求显式配置在 doctrine.yaml 的 url 或 dsn 之外的独立字段中。
正确设置字符集的位置是 doctrine.yaml
必须在 config/packages/doctrine.yaml 中的 doctrine.dbal 下添加 charset 和 default_table_options,否则即使数据库本身是 utf8mb4,新建表仍可能用默认 latin1 或 utf8(MySQL 5.7 以前行为)。
-
charset: utf8mb4控制连接层编码,影响SET NAMES行为 -
default_table_options: { charset: utf8mb4, collate: utf8mb4_unicode_ci }确保doctrine:schema:create或迁移建表时带正确选项 - 如果已存在表,该配置不自动修改,需手动执行
ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
serverVersion 必须匹配,否则 charset 可能失效
Doctrine 根据 serverVersion 决定是否启用 utf8mb4 相关语法。MySQL 8.0+ 默认支持,但若 DATABASE_URL 中写的是 ?serverVersion=5.7,Doctrine 会禁用 8.0 特性,导致 utf8mb4_0900_as_cs 等新 collation 不被识别,甚至建表失败。
- 检查
.env中DATABASE_URL的serverVersion值是否与实际 MySQL 版本一致(如8.0.33或8.4) - 运行
mysql --version或连接后执行SELECT VERSION();确认真实版本 - 不建议省略
serverVersion—— Symfony 8.0 不再自动探测,缺省会导致部分 DDL 语句生成错误
验证字符集是否生效的三个关键点
配完别急着写业务,先确认三层都对齐:连接、库、表。最容易漏的是第二层。
- 连上 MySQL 执行
SHOW VARIABLES LIKE 'character_set%';,确认character_set_client/connection/results都是utf8mb4 - 执行
SELECT DEFAULT_CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'your_db_name';,检查库级默认字符集 - 对任意实体生成的表,执行
SHOW CREATE TABLE your_table;,看CREATE TABLE末尾是否有DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
doctrine:schema:update --force 不会更新已有表的字符集,make:migration 也默认不检测这个维度。得自己写 SQL 迁移或用外部脚本批量修正。


















