ThinkPHP模型字段类型转换需显式配置且单向生效:读取时靠$type(TP8)或$cast(TP6)自动转,写入时不自动反向处理,JSON和时间字段另有约定;字段名须严格匹配、大小写敏感;类型转换仅作用于查询结果,写入前须手动转换。

ThinkPHP模型字段类型转换不是“自动发生”的事,而是必须显式配置、严格匹配规则才能生效的功能。核心在于:读取时靠 $type(TP8)或 $cast(TP6)控制基础类型转换;写入时不自动反向处理,得靠修改器或手动转换;JSON 和时间字段还有额外约定。
基础类型转换:读取时自动转,字段名必须完全一致
无论 TP6 还是 TP8,类型转换只在查询结果读取时触发,且对字段名大小写、下划线敏感——写成 'Status' 或 'status_id' 都不会生效。
- TP6 写
protected $cast = ['price' => 'float', 'status' => 'boolean'];,值必须用integer/boolean/json等全小写标识,int或bool会被静默忽略 - TP8 写
protected $type = ['price' => 'float', 'status' => 'boolean', 'created_at' => 'datetime'];,规则相同,不支持缩写 -
boolean类型会把数据库的1/0/TINYINT(1)转为 PHPtrue/false,但注意:值为2也会转成true(PHP 非零即真),这不是框架 bug
JSON 字段:不能只靠数据库类型,必须模型里声明
哪怕 MySQL 字段类型是 JSON,TP6 默认仍当字符串读;TP8 虽默认解码,但行为不稳定,推荐统一用模型配置。
- TP6 必须同时定义:
protected $json = ['config', 'extra'];声明哪些字段要 JSON 处理,再配protected $jsonType = ['config' => 'array'];指定目标类型 - TP8 可用
$json,也可依赖$type = ['config' => 'json'],但若字段存的是非法 JSON(如 null、空字符串、语法错误),会静默失败返回原始字符串 - 赋值时直接传数组:
$model->config = ['theme' => 'dark'];,框架自动json_encode;千万别先json_encode再赋值,否则双重编码
时间字段:格式化只影响读取,写入仍需标准输入
datetime 和 timestamp 类型能转成 Carbon 实例或格式化字符串,但仅限读取端——写入时仍得传时间戳、Carbon 对象或标准格式字符串(如 'Y-m-d H:i:s')。
立即学习“PHP免费学习笔记(深入)”;
- 写法示例:
'create_time' => 'datetime:Y-m-d'表示读出来是'2026-09-01'字符串;不加冒号则返回 Carbon 实例 - 如果数据库字段是
INT存时间戳,对应写'create_time' => 'timestamp';如果是DATETIME,就用datetime - 写入前别依赖模型自动转:前端传
'2026/09/01',得自己用strtotime()或Carbon::parse()转好再塞进save()
写入时的类型保障:不能只靠 $type/$cast
$type 和 $cast 是单向的——只在查出来时起作用。用户提交的数据、代码中 save() 的参数,框架不会自动帮你转成整数或布尔。
- 推荐做法:在控制器接收参数后立刻转换,例如
$data = ['status' => (int) $request->post('status'), 'price' => (float) $request->post('price')]; - 或在模型中定义修改器:
public function setStatusAttr($value) { return in_array($value, ['on', '1', 1, true], true) ? 1 : 0; } - TP8 开启
declare(strict_types=1)后,若没做预处理,错误类型数据可能静默存为0或空字符串,而不是报错,这点特别容易被忽略



















