thinkphp字段类型必须显式声明$type和$json才能自动转换,否则datetime为字符串、json为纯文本;$schema需写全字段,fields_cache需配置启用且调试模式下不生效。

ThinkPHP 里字段类型不会自动识别,不手动配 $type 或 $schema,DATETIME 就是字符串,JSON 就是纯文本,Carbon 对象、数组解码全都不会发生。
字段类型必须显式声明 $type 才生效
ThinkPHP 模型默认把所有字段当字符串处理,哪怕数据库里是 DATETIME 或 JSON 类型。只有你在模型里写明 $type = ['create_time' => 'datetime', 'config' => 'json'],读取时才会转成 Carbon 实例或 PHP 数组。
-
datetime字段配成'create_time' => 'datetime',才支持$user->create_time->diffForHumans()这类调用 -
JSON字段光写'data' => 'json'不够,还必须把字段名加进$json = ['data'],否则写入数组不会自动json_encode,读取也不会json_decode -
TIMESTAMP字段要配'update_time' => 'timestamp',配成datetime可能返回空或报错——因为底层对时间戳和日期对象的解析逻辑不同 - 别名字段(如
SELECT create_time AS ctime)必须单独在$type里配'ctime' => 'datetime',否则无效
$schema 和 fields_cache 别混用
$schema 是硬编码的字段定义数组,fields_cache 是运行时生成的缓存文件,二者目标都是避免首次查 SHOW COLUMNS,但启用方式和行为完全不同。
- 启用
fields_cache要在config/database.php里设'fields_cache' => true(注意不是fileds_cache),再执行php think optimize:schema,缓存文件会生成在runtime/schema/下 -
$schema必须写全表所有字段,漏一个就可能触发自动探测,导致类型错乱或缓存失效 - 调试模式下
fields_cache默认不生效,开发时容易误判“没起作用”,其实是环境覆盖了配置
字段命名与类型选择要符合团队规范
字段名统一小写+下划线,避免拼音、驼峰或歧义词;类型选择优先数字型而非字符型,尤其枚举值用 TINYINT,时间统一用 INT 存时间戳。
- 布尔类字段必须以
is_、has_、can_开头,如is_deleted、has_avatar - 所有实体表必须含
status(TINYINT)、time(INT)、del_time(INT)、remark(TEXT)字段,且status值域固定为 0(回收站)、1(正常)、2(禁用) - 外键字段名统一为
xxx_id,如user_id、category_id;无限极分类父级字段必须叫pid -
TEXT字段不设默认值,其它所有字段必须NOT NULL并提供合理默认值(如字符串用'',整数用0)
JSON 字段容易双重编码
ThinkPHP 的 JSON 自动编解码只在满足两个条件时才触发:字段在 $type 中声明为 'json',且字段名同时出现在 $json 数组里。一旦写入时传的是已编码字符串,就会被再次编码。
- 传数组:
$model->data = ['a' => 1]; $model->save();→ 正确存为{"a":1} - 传字符串:
$model->data = '{"a":1}'; $model->save();→ 实际存为"{\"a\":1}"(双重编码) - 数据库字段类型不是原生
JSON(比如用TEXT存)也能工作,但内容必须是合法 JSON,否则json_last_error()静默失败,无报错提示
最常被忽略的是 $json 数组和 $type 的配合关系,以及 fields_cache 在调试模式下的失效行为——这两点不验证,光看代码逻辑很容易以为“配了就一定生效”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











