thinkphp模型字段自动序列化需显式声明$type属性,如'options'=>'serialize',否则数组存取均为字符串;仅对string型数据库字段生效,json字段应声明为'json'类型以避免反序列化错误和安全风险。

ThinkPHP 的模型对数组字段做自动序列化,本质是靠 type 属性声明 + serialize 类型支持,不是靠魔法或配置开关。不显式声明字段类型,哪怕存的是数组,查出来也是字符串。
怎么让模型字段自动序列化和反序列化
在模型类中,通过 protected $type = [] 显式声明字段类型为 serialize:
protected $type = [
'options' => 'serialize',
'config' => 'serialize',
];
- 字段值写入数据库前,会自动调用
serialize()(PHP 原生);读取时自动unserialize() - 只对
string类型的数据库字段生效(如VARCHAR、TEXT),不支持JSON字段类型混用 - 如果字段已存在数据且是 JSON 格式,但类型声明为
serialize,读取时会因unserialize()失败而返回false或报错 - 不推荐把
json类型字段也设成serialize,两者语义和底层处理完全不同
为什么存数组后查出来还是字符串
最常见原因是没在模型里声明 $type,或者字段名拼写错误(比如数据库是 ext_info,但 $type 写成了 extinfo)。
- ThinkPHP 不会“猜测”哪个字段该序列化,必须精确匹配字段名
- 使用
Db::name()查询绕过模型时,$type完全不生效,得到的就是原始字符串 - 若用
toArray()导出数据,即使字段已正确反序列化,也可能因中间层转换再次转成字符串(尤其配合hidden/visible时) - 开启
debug模式后可看 SQL 日志,确认写入值是否已是a:1:{s:4:"key";s:5:"value";}这类格式
serialize 和 json 类型字段怎么选
优先用数据库原生 JSON 类型 + json 字段类型声明,而不是 serialize:
-
'data' => 'json'会走json_encode/json_decode,兼容性好、可读性强、支持 MySQL/PostgreSQL 的 JSON 查询函数 -
serialize是 PHP 特有格式,跨语言不可读,且unserialize()存在反序列化漏洞风险(尤其字段内容来自用户输入) - 如果必须用
serialize(例如遗留系统依赖__sleep/__wakeup),务必过滤输入,避免传入恶意构造的字符串 - MySQL 5.7+ 的
JSON字段在 ThinkPHP 中需配合json类型,不能写成serialize,否则会尝试反序列化 JSON 字符串而失败
真正要注意的不是“怎么开启序列化”,而是字段类型声明是否与数据库字段类型、数据来源、使用场景严格对齐。一个拼错的键名、一次绕过模型的查询、一种混用的类型声明,都可能让数组悄无声息地变成字符串。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











