ThinkPHP模型主键必须在模型类中显式声明protected $pk属性,严格匹配数据库字段名;自增主键需额外设置protected $auto = true;TP8还需声明protected $pkType类型。

ThinkPHP模型主键必须在模型类里显式声明,不能靠配置文件、动态调用或旧写法生效。默认只认 id 字段,如果数据库主键是 user_id、order_no 或其他名称,不设就会查不到数据、删错记录、拿不到新增ID。
TP6/TP8 必须写 $pk 属性
在模型类中添加一行:
-
protected $pk = 'user_id';—— 字符串形式,严格匹配数据库字段名(大小写、下划线都不能错) - 不能写成
userId、USER_ID或数组;不支持复合主键自动识别 - TP5 的
$_pk已废弃,写了也无效,必须改成$pk
自增主键要额外配 $auto = true
如果主键是自增的(比如 log_id),仅设 $pk 不够,insertGetId() 还是返回 0:
- 必须同时加
protected $auto = true; - 确保数据库该字段确实是
AUTO_INCREMENT(MySQL)或SERIAL(PostgreSQL) - 避免时间戳干扰:若启用了自动写入时间戳,建议关掉
$autoWriteTimestamp = false
TP8 要补充 $pkType 类型声明
TP8 对参数类型更严格,主键类型不声明会导致 find(1) 查不到、关联失效且无提示:
立即学习“PHP免费学习笔记(深入)”;
- 数字型主键:
protected $pkType = 'int'; - 字符串型主键(如 UUID、订单号):
protected $pkType = 'string'; - 类型声明紧接在
$pk后面,顺序无关但建议放一起
别踩这些坑
常见错误不是语法问题,而是配置被忽略:
- 在
Db::table()链式调用里用->pk('uid')—— TP6/TP8 不支持这种动态指定 - 把
$pk写在配置文件或构造方法里 —— 只有类属性protected $pk生效 - 多库项目误以为能全局统一设主键 —— 每个模型的
$pk是独立的,需逐个定义 - 升级 TP5 → TP6 后没清理
$_pk、$_auto等旧属性 —— 全部删掉重写



















