doctrine未操作预期数据库,主因是database_url配置错误、迁移状态表已标记但sql未生效、实体未被正确扫描或迁移类未用addsql()。

迁移命令显示成功但表结构没变,基本说明 Doctrine 没真正操作你预期的数据库——不是迁移逻辑错了,而是连接、识别或状态层面出了偏差。
数据库连接指向错误实例
这是最常见也最容易被忽略的原因。控制台提示 “Successfully migrated”,只代表迁移类执行完毕,不代表改了你本地正在用的那个库。
- 检查 .env 文件里的 DATABASE_URL 是否匹配目标数据库(比如误配成
sqlite:///%kernel.project_dir%/var/data.db,但你实际想改的是 MySQL) - 运行
php bin/console debug:config doctrine,确认输出中 connections.default.url 和驱动(pdo_mysql/pdo_pgsql)与你预期一致 - 若用 Docker,确保
DATABASE_URL中 host 是服务名(如db),不是localhost;端口是容器内端口(如3306),不是宿主机映射端口(如3307)
迁移文件未被 Doctrine 识别或已标记为“已执行”
Doctrine 不靠文件存在与否判断是否执行,而是查 doctrine_migrations 表(MySQL)或 doctrine_migration_versions 表(SQLite/PostgreSQL)里的记录。
- 运行
php bin/console doctrine:migrations:status,看你的迁移版本是否出现在 “Executed migrations” 列表里 - 如果已存在但结构没变,很可能是上次执行中断导致状态写入但 SQL 未生效,可手动从状态表中删掉对应行再重试
- 刚初始化项目时若提示 “10 migrations have no execution status”,需先运行
php bin/console doctrine:migrations:sync-metadata-storage初始化元数据表
实体变更未被 Doctrine 正确扫描
Migration 的 diff 依赖实体类的元数据。如果 Doctrine 根本没读到你改过的 Entity,自然不会生成差异。
- 确认实体类有 @ORM\Entity 或 #[ORM\Entity] 注解,且命名空间与文件路径严格对应(如
App\Entity\User必须在src/Entity/User.php) - 检查
config/packages/doctrine.yaml中 mappings 配置是否覆盖了你的实体目录(例如App\Entity\) - 运行
php bin/console doctrine:mapping:info,输出里必须包含你的实体类名;若没有,说明 Doctrine 完全没加载它
迁移类里用了不被识别的 SQL 写法
Symfony 4 默认使用 Doctrine Migrations v1.8+,它要求显式调用 $this->addSql() —— 直接用原生连接执行 SQL 不会纳入迁移事务,也不会触发结构变更。
- 错误写法:
$this->connection->executeStatement('ALTER TABLE user ADD avatar VARCHAR(255)'); - 正确写法:
$this->addSql('ALTER TABLE user ADD avatar VARCHAR(255)'); - 避免在
up()方法里混合使用 Schema API(如$schema->createTable())和addSql(),容易冲突











