必须新建迁移文件而非修改已执行文件:修改字段需装doctrine/dbal,用schema::table()调用change(),加删字段、改索引均须新迁移,且注意外键、引擎及数据兼容性。

不能直接改已执行过的迁移文件里的 up() —— Laravel 不会重新运行它,只会让本地和线上数据库结构越来越不一致。
修改字段类型或属性必须装 doctrine/dbal
比如要把 email 字段从 string(255) 改成 string(191)->nullable(),光写 $table->string('email', 191)->nullable()->change(); 是没用的。Laravel 默认不支持字段变更,底层依赖 doctrine/dbal 做类型比对和 ALTER COLUMN 生成。
- 先运行
composer require doctrine/dbal(Laravel 10+ 必须,旧版也建议装) - 确保 MySQL 连接配置中
'engine' => 'InnoDB',否则change()可能静默失败或报错 1005 -
change()只在Schema::table()闭包里生效,单独调用无效
加字段、删字段、改索引都走新迁移,别碰老文件
哪怕只是给 users 表加个 status 字段,也得新建迁移,而不是打开半年前那个 create_users_table.php 补一行代码。
- 命令:
php artisan make:migration add_status_to_users_table --table=users - 在新文件
up()里写Schema::table('users', function (Blueprint $table) { $table->string('status')->default('active'); }); - 删字段同理:
$table->dropColumn('old_field');(注意:MySQL 8.0+ 才支持一次删多个字段) - 改索引要先删再建,
dropIndex()+index()组合用,没有modifyIndex()
外键和引擎不匹配是回滚失败最常见原因
执行 php artisan migrate:rollback 报错 SQLSTATE[HY000]: General error: 1005 Can't create table,八成是外键或存储引擎问题。
- 检查
config/database.php中 MySQL 配置是否显式设了'engine' => 'InnoDB'(Laravel 9+ 默认为null,可能退化成 MyISAM) - 确认外键引用的表和字段确实存在,且类型完全一致(比如
bigInteger对bigInteger,不能integer对bigInteger) - 如果
down()里写了Schema::dropIfExists('posts'),但该表有外键被其他表引用,就会失败 —— 应该先删外键,再删表
真正容易被忽略的是:迁移只管结构,不管数据。字段改了长度或类型后,原有数据可能被截断或转换失败,这类风险不会在 migrate 命令里提示,得自己用 DB::statement() 或原生 SQL 预查。











