Doctrine Migrations 是 Symfony 7.4 生产环境必需的数据库版本控制基础设施,通过自动生成带时间戳的 PHP 迁移文件(如 Version20261010190200.php)实现结构变更,须先修改实体再执行 doctrine:migrations:diff,执行前需验证状态、检查 SQL 兼容性并确保事务开启,回滚依赖手动编写的 down() 方法,状态由 doctrine_migration_versions 表维护,严禁手动删表。

在 Symfony 7.4 中,Doctrine Migrations 不是可选项,而是生产环境必须依赖的数据库版本控制基础设施。它不靠手写 SQL 脚本,而是把每次结构变更固化为带时间戳的 PHP 迁移类,通过命令驱动执行与回滚,确保开发、测试、生产环境结构一致。
生成迁移文件:改实体 → 运行 diff
别手动写 up() 和 down() 方法——绝大多数场景应让 Doctrine 自动推导差异。正确流程是:
- 先修改实体类(如在 App\Entity\User 中添加
#[ORM\Column(type: 'string', length: 180)]$email 属性) - 运行命令生成迁移:
php bin/console doctrine:migrations:diff - 生成文件位于
migrations/Version20261010190200.php(含精确时间戳) - 若提示 “No changes detected”,检查实体是否漏了
#[ORM\Entity]或#[ORM\Table];或确认数据库中已有该字段但实体未同步 - 多数据库时需加
--em=other_manager指定实体管理器
执行迁移前必须验证三件事
直接运行 migrate 可能破坏线上数据。务必提前确认:
- 运行
php bin/console doctrine:migrations:status,确认“Available migrations”包含你刚生成的版本,“Executed migrations”尚未包含它 - 打开迁移文件,检查是否含手写的
$this->addSql()—— 若有,需人工验证其兼容性(例如 MySQL 8 的 JSON 类型写法 vs PostgreSQL) - 确认事务已启用:
config/packages/doctrine_migrations.yaml中transactional: true(Symfony 7.4 默认开启,但老项目升级后可能被覆盖)
安全执行与回滚到指定版本
迁移不是单向操作,回滚能力取决于 down() 方法的质量:
- 执行全部待处理迁移:
php bin/console doctrine:migrations:migrate - 回滚到某版本之前(例如撤销所有比
Version20240101AddOrderStatus更新的迁移):php bin/console doctrine:migrations:migrate Version20240101AddOrderStatus - 版本名必须完全匹配(大小写、下划线、数字),可用
--show-versions查看已应用列表 - 回滚失败主因是 down() 缺失或不完整:比如 up() 创建了外键但 down() 没先删约束;或 up() 添加字段后 down() 直接 dropColumn() 却未考虑存量数据
- 务必用
--dry-run预览真实 SQL:php bin/console doctrine:migrations:migrate Version20240101AddOrderStatus --dry-run,重点排查 DROP TABLE、ALTER TABLE DROP COLUMN 等高危语句
状态跟踪与常见陷阱
Doctrine 通过数据库中的 doctrine_migration_versions 表记录每个迁移的执行状态,严禁手动删表或修改该表内容。
-
doctrine:migrations:status是日常检查核心命令,能快速识别“卡住”的迁移 - 空 down() 方法或仅含
$this->abortIf(true, ...)表示不可回滚,执行时会中断 - 避免在 up() 中写
$this->addSql('DROP TABLE users')—— 这类非幂等、无上下文判断的操作极易导致部署失败 - 迁移文件一旦提交到 Git,就不可修改。若发现错误,应生成新迁移修复,而非编辑旧文件


















