模型字段类型转换失败主因是字段名大小写不一致、类型标识符错误或混淆$cast/$json/$type作用范围;字段名须与数据库列名完全一致,类型标识符仅支持小写英文,三者生效时机不同且不可混用。

模型字段类型转换失败,通常不是框架坏了,而是配置没对上、写法有误,或者混淆了不同机制的生效范围。核心问题往往出在三个地方:字段名大小写不一致、类型标识符写错、或误以为某个配置能双向生效。
字段名必须和数据库列名完全一致
ThinkPHP 6 的 $cast、$json、$type 等配置,全部严格区分大小写。哪怕数据库字段是 user_name,你在模型里写成 'UserName' 或 'username',转换都会静默失效——不报错,也不执行。
- 检查方式:用
var_dump($model->getRawData())看原始值是不是字符串;再对比数据库建表语句里的字段名(包括下划线、驼峰) - 常见翻车点:
created_atvscreate_time、statusvsStatus、MySQL 默认小写但开发环境开了大小写敏感 - 解决办法:统一用小写下划线风格定义字段,模型配置也照抄,不加任何转换逻辑
类型标识符只能用官方支持的小写英文
$cast 只认 integer、float、boolean、string、array、json、datetime、timestamp。写成 int、bool、str 或首字母大写,TP6 会直接忽略,连 warning 都不抛。
-
'price' => 'float':适合 DECIMAL 或带小数的数字 -
'status' => 'boolean':把 1/0/'1'/'0' 转为 true/false,但注意 MySQL TINYINT(1) 存 2 也会转成 true(PHP 非零即真) -
'meta' => 'json':仅当字段内容是合法 JSON 字符串时才解码成功,null 或空字符串会保持原样
别混淆 $cast、$json 和 $type 的作用边界
这三个配置看起来都跟“类型转换”有关,但触发时机和能力完全不同:
立即学习“PHP免费学习笔记(深入)”;
-
$cast:只在读取时生效(查出来自动转),写入
save()不处理,需配修改器或手动清洗 -
$json:专用于 JSON 字段,读取时
json_decode,写入时json_encode,但要求字段名必须显式声明在数组里 -
$type(如
'create_time'=>'timestamp'):只在写入时把字符串转时间戳存库,读出来还是整数,不是格式化输出
如果同时用了 $json = ['config'] 和 $withAttr = ['config'=>'json_decode'],会导致重复解码,第二次 json_decode 作用在数组上返回 null,数据就丢了。
写入时想强制转类型?得靠修改器或事件
$cast 是单向的,只管读不管写。想让传进来的字符串价格自动转 float、传进来的 JSON 字符串自动转数组,必须补上对应逻辑:
- 定义修改器:
public function setPriceAttr($value) { return (float) $value; } - 或在
before_write事件里统一处理:$this->price = (float) $this->price; - 对 JSON 字段,直接赋值数组即可:
$model->config = ['theme' => 'dark'];,别先json_encode()再赋值,否则会双重编码



















