doctrine:migrations:diff是核心命令,通过对比实体与数据库结构自动生成安全可逆的php迁移类;未生成内容最常见原因是实体缺少@orm\entity、@orm\table或@orm\column注解,或数据库已存在对应字段而实体未同步。

直接生成迁移文件再执行,别手写 SQL;doctrine:migrations:diff 是核心命令,它靠对比实体和数据库结构来生成安全、可逆的 PHP 迁移类。
为什么 doctrine:migrations:diff 没生成任何内容?
最常见原因是 Doctrine 没“看见”你的变更。它只认带完整映射注解的实体字段:
-
@ORM\Entity和@ORM\Table缺一不可,否则整个类被忽略 - 新增字段必须有
@ORM\Column(哪怕只是@ORM\Column(type="string")),漏掉就等于没改 - 如果数据库里已有该表/字段,但实体没同步(比如手动加了列),
diff会认为“一致”,不生成迁移 - 多连接时默认只扫
default实体管理器,要指定用--em=other_manager
make:migration 和 doctrine:migrations:diff 有什么区别?
本质一样,都是触发 diff 逻辑,但行为路径不同:
-
make:migration是 Symfony Maker Bundle 提供的封装,会先检查DoctrineMigrationsBundle是否已启用,缺依赖就报错提示 -
doctrine:migrations:diff更底层,不依赖 Maker Bundle,适合 CI 或脚本调用,但不会自动帮你装包 - 两者生成的迁移文件格式、命名规则、
up()/down()结构完全一致
执行迁移前必须确认的三件事
跳过这步容易在生产环境丢数据或锁表:
- 跑
doctrine:migrations:status:确认新生成的版本号出现在 “Available migrations” 里,且 “Executed migrations” 中没有它 - 打开迁移文件,检查是否含
$this->addSql()手写语句——如果有,确认它兼容目标数据库(比如 PostgreSQL 不支持INT AUTO_INCREMENT) - 确认
config/packages/doctrine_migrations.yaml中transactional: true(默认开启,但老项目可能被关掉);关掉后单个迁移失败会导致部分执行、状态错乱
怎么让迁移只管带前缀的表(比如 pp_ 开头)?
Doctrine 默认扫描全库,但可通过正则过滤。在 config/packages/doctrine.yaml 的 dbal 下加配置:
doctrine:
dbal:
schema_filter: ~^pp_.*~
这个正则表示“只处理以 pp_ 开头的表名”,其他表(如 log_*、cache_*)会被完全忽略。注意:
- 正则必须用波浪线
~包裹,不是引号 - 修改后需清缓存:
php bin/console cache:clear,否则diff仍按旧规则扫描 - 该配置也影响
doctrine:schema:update --force,慎用于已有混合表结构的库
真正麻烦的不是生成迁移,而是确保 down() 方法能严格反向执行——它不会自动生成,你得自己写对称逻辑;比如 up() 里 $schema->createTable('foo'),down() 就得写 $schema->dropTable('foo'),少一个字母都可能让 rollback 失败。











