ThinkPHP模型中protected $type需定义为['字段名'=>'类型名'],仅在data()或属性赋值后调用save()时生效,批量save($data)会绕过转换;类型名须用integer、boolean等内置名,不可用int或bool。

模型里怎么写 protected $type 才生效
ThinkPHP 的模型字段类型约束不是写完就自动转的,它只在 save()、create()(V6 已废弃)、data() 后调用 save() 时触发,且仅对当前模型实例的属性赋值过程起作用。
常见错误是:直接给数组赋值再 save(),比如 $model->save(['id' => '123', 'status' => '1']) —— 这种写法绕过了类型转换逻辑,$type 完全不生效。
-
$type必须定义在模型类中,格式为['字段名' => '类型名'],例如protected $type = ['id' => 'integer', 'score' => 'float', 'is_vip' => 'boolean'] - 类型名必须是 ThinkPHP 内置支持的(如
integer、float、boolean、timestamp、datetime、json),不能写int或bool - 对
datetime类型,会尝试用strtotime()解析;json类型要求原始值是字符串,否则会跳过转换
save() 时字段没转类型?检查是否用了批量赋值
ThinkPHP 默认禁止未声明的字段写入(strict 模式),但更隐蔽的问题是:用了 allowField() 或显式传入数组,等于跳过了模型的属性设置流程,自然也跳过了类型转换。
正确做法是先用 data() 或直接赋值,再 save():
$user = new User(); $user->data(['id' => '123', 'status' => '1']); // ✅ 触发 $type 转换 $user->save(); // 或 $user = new User(); $user->id = '123'; // ✅ 自动转 integer $user->status = '1'; // ✅ 自动转 boolean('1' → true) $user->save();
- 如果用了
$model->save($data, [], ['validate' => true]),validate 不影响类型转换,该跳过还是跳过 - V6.1+ 中
saveAll()对每个模型实例单独处理,$type有效;但若传入二维数组并开启batch,则退化为 SQL 批量插入,不走模型逻辑 -
update()静态方法默认不经过模型实例,除非显式 new 模型再调用
boolean 类型为什么有时转成 0/1,有时是 true/false
ThinkPHP 的 boolean 类型转换行为取决于后续操作:存库前转成整数(true→1, false→0),但模型属性读取时仍保持布尔值。问题多出在 JSON 序列化或 API 返回时没注意类型丢失。
- 数据库字段要是
TINYINT(1)或BOOLEAN(实际也是 tinyint),否则存不进非 0/1 值 - 如果字段定义了
boolean类型,但入库后查出来是字符串"1",大概率是 PDO 没设PDO::ATTR_EMULATE_PREPARES => false,导致 MySQL native type 未启用 -
json类型字段若原始值是 PHP 数组,$type会自动json_encode();但如果已是个 JSON 字符串,不会重复编码 —— 容易导致双层转义
想让类型校验更严格?别只靠 $type
$type 是弱转换,不是强校验。它把 'abc' 转 integer 得到 0,把 null 转 boolean 得到 false,不会报错也不会中断流程。
- 真正需要强约束(比如不允许空字符串进 int 字段),得配合验证器:
rule('age', 'require|number|between:1,120') -
$type对关联属性、JSON 字段内嵌结构完全无效,例如'profile' => 'json'只确保整个字段是合法 JSON 字符串,不校验里面age是不是数字 - 自定义类型转换要继承
think\Model并重写getAttr()/setAttr(),但注意 V6.0+ 中推荐用访问器(getxxxAttr)替代
类型约束容易被当成“校验开关”,其实它只是数据流转中的一次温和整形。真要拦住非法输入,验证器和数据库 schema 才是第一道防线。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











