laravel 10 和 11 在数据库迁移中字段类型与索引处理逻辑完全一致,外键需严格匹配类型、软删除须联合 deleted_at 建唯一索引、字段修改必依赖 doctrine/dbal 并显式调用 change() 或 renamecolumn(),约束命名及回滚机制均兼容。

Laravel 10 和 11 在数据库迁移层面的字段类型与索引处理逻辑高度一致,没有引入破坏性变更。所谓“新版本优化”,实质是延续已有机制、强化约束一致性,并在开发体验上做细微提升——不是语法变新了,而是旧规则更不容忽视了。
字段类型必须严格匹配,两个版本都一样严
外键字段类型不匹配,是迁移失败最常见原因,且在 Laravel 10 和 11 中报错行为完全相同:
- ✅ 正确写法(通用):
$table->foreignId('user_id')->constrained()->onDelete('cascade') - ❌ 错误写法(两个版本均失败):
-
$table->bigInteger('user_id')->unsigned()(类型虽无符号但非foreignId(),缺约束声明) -
$table->unsignedBigInteger('user_id')(未调用->foreign()或->constrained(),不会建外键)
MySQL 的 errno 150 错误在两个版本中表现一致,根源仍是底层字段类型与父表主键(如bigincrements)不兼容。
-
唯一索引语义未变,但软删除场景需显式联合$table->string('email')->unique() 在 10 和 11 中生成的都是单列 B-tree 唯一索引,行为无差异。
但若模型启用 SoftDeletes,仅对 email 加唯一索引会导致逻辑删除后仍可重复注册:
- ✅ 正确做法(两版本通用):
$table->unique(['email', 'deleted_at']) - ⚠️ 注意:
deleted_at允许 NULL,而 MySQL 规定NULL != NULL,因此多个已删除记录可共用同一邮箱——这是设计特性,不是 bug。
字段修改仍依赖 doctrine/dbal,且必须显式调用 change()
无论是 Laravel 10 还是 11:
- 修改字段长度、类型或属性(如
string('name', 255) → string('name', 191)),仅改定义不行,必须加->change() - 重命名字段必须用
->renameColumn('old', 'new'),不能靠->change()实现 -
doctrine/dbal是运行时强制依赖,不是可选包;不安装会导致change()和renameColumn()静默跳过或直接报错
索引与约束命名规则、回滚机制完全兼容
- 外键默认名:
{table}_{column}_foreign(如posts_user_id_foreign) - 唯一索引默认名:
{table}_{column}_unique(如users_email_unique) - 删除约束写法统一:
$table->dropForeign(['user_id'])、$table->dropUnique('users_email_unique') - 回滚只支持按 batch(批次),
php artisan migrate:rollback --step=1在两个版本中均表示回退最近一次migrate执行的所有迁移文件,不是单个文件
不复杂但容易忽略











