thinkphp模型字段类型转换需显式配置$type属性,如'id'=>'integer'、'create_time'=>'datetime'等,且必须配合$json等属性才能实现json自动编解码;转换仅在模型实例属性访问或toarray()时生效,db类查询不触发。

ThinkPHP 的模型字段类型转换不是自动发生的,必须显式配置 $type 属性,否则哪怕数据库是 INT 或 DATETIME,查出来的值也全是字符串。
怎么在模型里配 type 字段类型
在模型类中定义 protected $type = [],键为数据库字段名(严格匹配,含下划线),值为类型标识符。常见写法:
-
'id' => 'integer'—— 转成整型(注意不是int) -
'create_time' => 'datetime'—— 返回 Carbon 实例(TP6.1+)或 DateTime 对象 -
'status' => 'boolean'—— 只对0/1/'0'/'1'/true/false生效,其他字符串如'on'不会转 -
'price' => 'float'—— 别用double,框架不识别 -
'data' => 'json'—— 仅声明类型转换,不会自动编解码;要真正生效,还需配合protected $json = ['data']
JSON 字段要真正自动处理,得两步走
只写 'data' => 'json' 在 $type 里,读出来仍是字符串。必须同时做:
- 声明类型:
protected $type = ['data' => 'json'] - 启用编解码:
protected $json = ['data'] - (可选)指定解码为数组:
protected $jsonType = ['data' => 'array'],这样$model->data就是 PHP 数组而非 stdClass 对象 - 写入时直接赋数组:
$model->data = ['tags' => ['php', 'tp']],框架自动json_encode;别手动编码再赋值,否则双重编码
时间字段的常见写法和陷阱
datetime 和 timestamp 行为不同,选错容易出问题:
-
'updated_at' => 'datetime':返回 Carbon/DateTime 对象,支持链式调用如->toDateTimeString() -
'updated_at' => 'timestamp':返回整型时间戳;非法值(如空字符串)会静默转成0 - 格式定制可写成
'create_time' => 'datetime:Y/m/d H:i:s'或统一设protected $dateFormat = 'Y-m-d'; - 若数据库是
TIMESTAMP,但模型写'updated_at' => 'datetime',可能带时区偏移;写'date'又会丢时间部分——优先用datetime,后续按需格式化
类型转换什么时候生效、为什么没生效
转换只在模型实例中触发,且依赖调用方式:
- ✅ 有效场景:通过属性访问(
$user->id)、toArray()、getAttr() - ❌ 无效场景:用
getData('id')拿到的是原始值;用Db::table()->where(...)->select()直接查,不走模型逻辑,转换完全不触发 - 常见失效原因:
- 模型没继承
think\Model,而是用了think\db\Query - 字段名大小写或下划线不一致,比如数据库是
create_time,$type写成'createTime' - 查询时用了
field('id,name'),但漏写了要转换的字段(如status),没查的字段自然不走转换
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











