需在模型中设置$primarykey、$incrementing和$keytype三个属性:$primarykey指定主键字段名,$incrementing=false禁用自增,$keytype='string'声明字符串类型,三者缺一不可。

默认情况下,Laravel 的 Eloquent 模型假定数据表的主键字段叫 id,且是自增整型。如果实际表结构用的是别的字段名(比如 user_id、uuid 或 code),不改配置会导致查询失败、创建报错或关联失效。
怎么告诉模型主键字段不是 id
在对应模型类中,显式设置 $primaryKey 属性即可:
class User extends Model
{
protected $primaryKey = 'user_id';
}
这会覆盖默认行为,后续所有查询(User::find(123))、新增(save())、关联($post->user)都会基于 user_id 字段操作。
- 该字段仍需是主键(数据库层面),否则
find()等方法可能返回意外结果 - 若字段类型不是整型(如字符串 UUID),还需配合
$keyType = 'string' - 如果表没有自增逻辑(如手动维护 ID),建议同时设置
public $incrementing = false
主键不是自增整型时必须处理的两个属性
当主键是 UUID、编码字符串或数据库未启用 auto_increment 时,只改 $primaryKey 不够,Eloquent 仍会按整型+自增逻辑生成 SQL,导致插入失败或 ID 被覆盖。
需同步调整:
class Product extends Model
{
protected $primaryKey = 'sku';
public $incrementing = false;
protected $keyType = 'string';
}
-
$incrementing = false:禁用自增逻辑,避免 INSERT 语句里带id字段或尝试获取最后插入 ID -
$keyType = 'string':影响whereKey()、路由隐式绑定等底层类型判断,防止整型强制转换出错 - 如果不设
$keyType,而主键是字符串,find('ABC')可能被转成0导致查不到
使用非 id 主键时关联关系要注意什么
Eloquent 关联默认按 id 匹配外键,比如 belongsTo(User::class) 会自动找 user_id 字段并关联到 User::$primaryKey(即 id)。如果你的 User 表主键是 user_id,但没改模型配置,关联就会查错字段。
- 确保关联方模型已正确定义
$primaryKey,否则with('user')返回空或报错 - 若外键名不遵循 Laravel 约定(如叫
owner_code),需在belongsTo()中显式传参:belongsTo(User::class, 'owner_code', 'user_id') - 多对多中间表里的外键字段名,也要和双方模型的
$primaryKey保持一致,否则sync()失效
最常被忽略的是 $incrementing 和 $keyType 的组合设置——只改字段名,不关自增或不声明类型,尤其在 UUID 场景下,保存后查不到、路由绑定 404、分页错乱都是典型表现。










