用id(),它生成BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY并兼容所有数据库驱动;手动用unsignedBigInteger('id')->primary()->autoIncrement()在MySQL 8.0+严格模式下可能失效,且与Laravel主键处理逻辑冲突。

laravel迁移中设置自增主键用id()还是unsignedBigInteger('id')->primary()->autoIncrement()
直接结论:用id(),别手写unsignedBigInteger加autoIncrement()——它在MySQL里不生效,且和Laravel内部ID生成逻辑冲突。
原因很简单:autoIncrement()只是给字段加AUTO_INCREMENT属性,但Laravel的id()方法还会额外调用->primary()并确保字段是UNSIGNED,更重要的是,它会触发Schema Builder对主键的特殊处理(比如避免在SQLite里出错)。
-
id()→ 生成id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,兼容所有驱动 -
unsignedBigInteger('id')->primary()->autoIncrement()→ 在MySQL里看似一样,但某些版本(尤其MySQL 8.0+ with strict mode)可能忽略autoIncrement(),导致插入时报Field 'id' doesn't have a default value - 如果你手动指定了
id字段又没设->nullable(false)或->default(null),部分数据库(如PostgreSQL)会直接拒绝迁移
想用非id字段做自增主键(比如order_no)怎么办
Laravel不支持非id字段自动设为自增主键——这不是语法限制,而是设计约束。Eloquent默认只认id为主键,且autoIncrement()只在主键字段上被Schema Builder真正采纳。
如果你真需要类似效果(例如订单号自增),得换思路:
- 保持
id为自增主键,另加一个order_no字段(string或bigInteger),用模型事件或数据库触发器生成 - 迁移里不要给
order_no加autoIncrement(),它不会起作用;加了反而让开发者误以为“数据库在管”,结果应用层漏写生成逻辑 - 如果坚持用
order_no当主键,必须手动设protected $primaryKey = 'order_no',同时禁用incrementing = false,并自己保证唯一性和递增性——这已脱离Laravel“约定优于配置”的轨道,容易在save()、create()时出问题
unsignedBigInteger字段能不能单独设autoIncrement
不能。MySQL要求AUTO_INCREMENT必须配合PRIMARY KEY或UNIQUE索引,且只能有一个字段带该属性。Laravel的autoIncrement()方法底层只是加AUTO_INCREMENT关键字,不自动补索引。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
常见翻车现场:
-
Schema::table('users', function (Blueprint $table) { $table->unsignedBigInteger('seq')->autoIncrement(); });→ 迁移成功,但字段实际不自增,插入时全报0或NULL - 有人补上
->unique(),结果MySQL报错:AUTO_INCREMENT column must be defined as a key(必须是KEY,而UNIQUE不够) - 正确做法:如果真要额外自增列,得显式建主键或联合主键,比如
$table->unsignedBigInteger('seq')->primary(),但这会覆盖原id主键,风险极高
升级旧项目时遇到unsignedBigInteger主键迁移失败
老项目用increments()(已废弃)或手写bigIncrements(),升级到Laravel 9+后跑迁移常卡在SQLSTATE[HY000]: General error: 1075 Incorrect table definition——本质是MySQL严格模式下,不允许AUTO_INCREMENT字段没设NOT NULL。
修复关键点就一个:检查迁移文件里所有unsignedBigInteger字段,确认是否显式写了->nullable(false)或依赖->primary()隐式设为NOT NULL。
- 错误写法:
$table->unsignedBigInteger('user_id');→ 没NOT NULL,MySQL 8.0+直接拒迁 - 正确写法:
$table->unsignedBigInteger('user_id')->nullable(false);或更自然地用$table->foreignId('user_id')(Laravel 8+推荐) - 如果字段本该是外键,优先用
foreignId(),它自动带unsignedBigInteger+NOT NULL+ 索引,还省一行->constrained()
最易被忽略的一点:autoIncrement()不是“让字段变自增”的开关,而是“告诉Schema Builder:请按自增主键方式生成DDL”。它只在id字段或明确设为primary()的字段上可靠生效。别的地方加了,等于贴了个无效标签。

















