加字段需明确位置、是否自增及历史数据处理:用Schema::table()新增字段,非主键自增须用bigIncrements()并手动加唯一或主键约束,已有数据需显式设default或nullable,否则迁移报错。

直接加字段没问题,但「加在哪」「要不要自增」「已有数据怎么处理」这三件事不提前想清楚,迁移一跑就报错。
用 Schema::table() 添加字段最稳妥
别在 create 迁移里硬改——那是建表用的。新增字段一律走 table 迁移:
- 运行
php artisan make:migration add_status_to_users_table - 在
up()里写$table->string('status')->default('active')->after('email') -
after('email')能控制位置,但仅对 MySQL 有效;SQLite 和 PostgreSQL 会忽略它 - 如果字段要允许为空,显式写
->nullable(),别依赖默认行为
increments() 和 bigIncrements() 不是万能的
想加一个自增字段?别直接写 $table->increments('sort_order') —— Laravel 8+ 已弃用,9+ 直接报错。
- 主键用
$table->id()(等价于bigIncrements('id')) - 非主键自增字段,必须用
$table->bigIncrements('order_no'),再手动加->primary()或->unique() -
$table->integer('counter')->autoIncrement()❌ 完全无效,生成的 SQL 没有 AUTO_INCREMENT - 已有表加自增字段?先加普通字段,再用
DB::statement('ALTER TABLE ... MODIFY ... AUTO_INCREMENT PRIMARY KEY')补约束
已有数据时,default 和 nullable 必须二选一
给带历史数据的表加字段,MySQL 会强制你说明新列的初始值。
- 写
->default('pending'):所有老记录该字段都填'pending' - 写
->nullable():老记录该字段为NULL,但后续插入必须显式赋值或允许空 - 两者都不写?迁移直接失败,报错类似
SQLSTATE[HY000]: General error: 1171 Duplicate entry '' for key 'users.status' - 如果字段类型是
boolean,记得用->default(false),别传字符串'0',Eloquent 会当字符串存
真正容易翻车的是「字段位置 + 自增 + 历史数据」三者叠加——MySQL 要求自增列必须是索引的一部分,而 after() 又不跨数据库兼容。线上表结构变更前,先在测试库跑一遍原生 SHOW CREATE TABLE 看最终 SQL 长什么样。


















