thinkphp模型type属性需字段名完全匹配且仅在读取时生效,使用integer/float/string等全小写标识符,写入不自动转换,非法值转换可能为0或null。

ThinkPHP 模型的 type 属性怎么写才生效
模型里定义 type 不起作用?大概率是没配对字段类型或没触发读取逻辑。ThinkPHP 的类型转换只在模型读取数据(select、find、get 等)时自动执行,写入(save、create)默认不反向转换。
必须确保:
-
type数组键名和数据库字段名完全一致(区分大小写) - 字段值来自数据库查询结果(不是手动 new Model()->data([...]))
- 模型开启了自动转换(默认开启,但若手动调用
toArray(false)会跳过)
示例:
protected $type = [
'status' => 'integer',
'price' => 'float',
'name' => 'string'
];
integer / float / string 和 int / float / str 的区别
ThinkPHP 6+ 要求使用全小写英文类型标识符,如 integer、float、string;写成 int、str 或首字母大写(Integer)均无效,也不会报错,只是静默忽略。
常见错误现象:var_dump($model->status) 仍是字符串,但 gettype($model->status) 显示为 string —— 实际是因为 type 配置未被识别,转换根本没发生。
可用的合法类型包括:integer、float、string、boolean、array、object、datetime、timestamp、json。
为什么 status 字段转了 integer 却还是 null
空字符串 ''、NULL、无法解析的字符串(如 'abc')在转 integer 时会变成 0,但 ThinkPHP 在遇到非法值且配置了 strict 模式时可能返回 null —— 实际上,默认不 strict,所以更可能是字段本身为 NULL 且数据库允许 NULL,而 PHP 的 (int) null 结果是 0,但模型内部做了空值保护逻辑。
排查建议:
- 先查原始数据:
echo $model->getData('status');看原始值是不是null或空 - 确认数据库字段是否为
NOT NULL,否则需配合default或业务层兜底 - 避免依赖自动转换做数据校验,它不处理非法输入,只做尽力转换
需要写入时也自动转类型?得自己动手
ThinkPHP 的 type 是单向的(读取时转换),写入时不自动反向处理。比如你把 price 设为 float,读出来是 19.9,但存回去时传 '19.90' 字符串,框架不会帮你转成 float 再入库 —— 它直接原样进 SQL 参数绑定。
如果要写入前也标准化类型,推荐两种方式:
- 重写模型的
setAttr方法,例如:public function setPriceAttr($value) { return (float) $value; } - 在
save()前统一处理:$model->price = (float) $model->price;
注意:用 setAttr 时,若字段还涉及时间/JSON 等复杂类型,需额外判断,别一概 (float) 强转。
真正容易被忽略的是:类型转换发生在模型属性访问阶段,而不是数据库字段映射阶段。也就是说,即使你改了 $type,旧数据已经加载进对象属性,再次访问不会重新转换 —— 必须重新查询或调用 refresh() 才触发。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











