迁移失败后最该盯住的是doctrine执行的sql语句、元数据差异及数据库真实状态与预期的矛盾点,而非报错堆栈顶端的“migration failed”;日志暴露不一致处即修复起点。

迁移失败后,日志里最该盯住的不是报错堆栈顶端那句“Migration failed”,而是Doctrine 实际执行的 SQL 语句、它比对的元数据差异、以及数据库真实状态与预期之间的矛盾点。日志本身不直接告诉你“哪里错了”,但会暴露 Doctrine 在哪一步发现不一致——而这正是修复的起点。
看 SQL 执行失败的具体语句
Doctrine 日志(尤其开启 --verbose 或配置 doctrine.dbal.logging: true)会打印出正在执行的 CREATE TABLE、ALTER COLUMN 等语句。重点检查:
- 是否在对一个已存在的表执行
CREATE TABLE(说明doctrine_migration_versions表缺失记录或状态脱节) - 是否尝试给非空字段加
NOT NULL约束(而表中已有 NULL 数据) - 是否执行了
DROP COLUMN却没先处理依赖该列的索引或外键 - PostgreSQL 下是否出现
relation "xxx" does not exist—— 很可能表名大小写不匹配(如实体写@ORM\Table(name="User"),但数据库里是user)
看 diff 比对时识别出的“变化”是否合理
如果失败发生在 doctrine:migrations:diff 阶段(比如生成了危险语句或根本没生成),打开日志中隐含的 schema diff 输出(或手动运行 php bin/console doctrine:schema:update --dump-sql):
- 是否显示要删掉主键自增?→ 检查 PostgreSQL 实体是否误配
options={"autoincrement":true}或strategy="SEQUENCE"缺sequenceName - 是否显示要修改字段长度(如从
VARCHAR(191)改成VARCHAR(255))?→ 实体里漏写了@ORM\Column(length=255),DBAL 推导出的长度和实际不符 - 是否完全没输出 SQL?→ 实体类缺
@ORM\Entity注解,或config/packages/doctrine.yaml中mappings路径未覆盖你的实体目录
看数据库连接与状态表相关提示
很多“迁移失败”其实卡在基础设施层,日志里常有隐蔽线索:
-
Connection refused或could not find database file→DATABASE_URL指向错误(比如本地用 sqlite,部署却没切 MySQL;或 Docker 内 PHP 连localhost而非服务名database) -
Class 'PDO' not found或DriverException: could not find driver→ PHP 缺pdo_pgsql/pdo_mysql扩展 -
Table "doctrine_migration_versions" doesn't exist→ 迁移表本身没创建,需先跑php bin/console doctrine:migrations:install(Symfony 4.3+ 自动触发,但老项目或手动删表后需补) -
No migrations to execute且你确定刚生成了文件 →doctrine_migration_versions表里没有对应版本记录,可能是迁移文件被重命名、删了,或之前执行中断导致状态写入不全
看缓存与元数据是否被旧信息干扰
Symfony 4 的 Doctrine 缓存机制容易让改动“看不见”:
- 改完实体后立刻跑
diff却无反应 → 清缓存:php bin/console cache:clear(开发环境)或php bin/console cache:clear --env=prod(生产) - 日志里反复出现同一张表的字段被“反复添加又删除” → 元数据缓存未刷新,或实体注解与数据库结构存在隐形不一致(如索引名不同但字段组合相同,Doctrine 不校验索引名)
- 运行
php bin/console doctrine:mapping:info输出里没有你的实体类 → 说明 Doctrine 根本没加载它,检查命名空间、文件路径、@ORM\Entity注解是否存在











