database_url必须写在.env文件中且格式正确,doctrine仅通过该环境变量连接数据库;需包含mysql://协议、127.0.0.1地址、显式serverversion、url编码密码及charset=utf8mb4参数,并区分多环境配置。

DATABASE_URL 必须写在 .env 里,不能只改 doctrine.yaml
Doctrine 连接数据库时,只从 DATABASE_URL 环境变量读取连接串,doctrine.yaml 里的 url 字段只是个占位符,实际值必须是 '%env(resolve:DATABASE_URL)%'。如果你直接在 YAML 里硬编码 URL,它会被忽略或触发解析错误。
正确做法是:打开项目根目录下的 .env 文件,确保有且仅有一行以 DATABASE_URL= 开头(注意等号前后不能有空格),值用双引号包裹。
mysql:// 协议头、127.0.0.1 和 serverVersion 缺一不可
常见连不上是因为协议或地址写错,不是密码或库名问题。
-
mysql://必须完整写出,不能省略为mysql:或漏掉// - 用
127.0.0.1,别用localhost:后者会触发 Unix socket 连接,报错No such file or directory -
serverVersion必须显式指定,如?serverVersion=8.0;MySQL 5.7 就写5.7,否则 DQL 查询或迁移可能生成不兼容语法 - 如果 MySQL 是 Docker 官方镜像(尤其是 8.0+),默认禁用
mysql_native_password插件,需手动执行ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx'
密码含 @ / : 等字符必须 URL 编码
URL 解析器会在第一个 @ 处截断用户/密码分界,所以 pass@word 会被当成用户名 pass、密码为空。不编码就必然连不上。
-
@→%40 -
/→%2F -
:→%3A -
?、=、&同理,只要出现在密码里就得编码 - 推荐用 PHP 的
rawurlencode()处理,比如rawurlencode('my@p/ass')返回my%40p%2Fass
charset=utf8mb4 和多环境隔离要提前设好
不加 &charset=utf8mb4,存 emoji 或四字节中文会变问号或报错;不区分环境,开发和生产共用一个 .env,上线后容易泄露敏感配置。
- 连接串末尾加上
&charset=utf8mb4,这是现代 MySQL 应用的底线配置 - 开发用
.env.local(gitignore 默认已忽略),生产用.env.prod,并在doctrine.yaml中保持url: '%env(resolve:DATABASE_URL)%' - 生产密钥(如数据库密码)别硬塞进
.env.prod,改用secrets:set DATABASE_PASSWORD --env=prod加密存储 - 验证是否生效:运行
php bin/console doctrine:database:create --if-not-exists,成功返回Created database `xxx`才算真正通了
最容易被忽略的是 serverVersion 和密码编码——这两项不出错时一切正常,一出错就表现为“连得上但建表失败”或“Access denied”,排查方向却全跑偏。别猜,先检查 URL 里有没有 ?serverVersion=,再拿密码去 rawurlencode() 一遍。











