本帖最后由 mark35 于 2012-12-3 19:25 编辑
因为在个人空间列表中被隐藏,故此存档 http://xiaozhong.biz/thread-287-1-1.html
Discuz系列对于设置项中数据类型(比如版块设置)采用序列化方式(serialize)保存,读取时使用unserialize()反序列化字符串为数组
序列化这种方式有个致命的缺点:字符集会影响序列化结果
对于这个数组序列化
- $s = [1, '小众站长网', 'http://www.xiaozhong.biz'];
- echo serialize($s);
复制代码 UTF-8环境下结果为a:3:{i:0;i:1;i:1;s:15:"小众站长网";i:2;s:24:"http://www.xiaozhong.biz";}
GB2312环境下结果为a:3:{i:0;i:1;i:1;s:10:"小众站长网";i:2;s:24:"http://www.xiaozhong.biz";}
注意看 “小众站长网”前面的数字,UTF-8下面为15,GB下面为10. 这是因为在UTF-8字符集中中文字长3-4个字节,而在GB/GBK中中日韩问字长都固定为2个字节。至于英文在两种字符集中都占1字节所以序列化长度是固定的
如此不同的序列化结果产生的兼容性在于不同字符集的discuz版本的数据库中保存的设置项目值是不相同的——在进行字符集版本转移时无法直接导出数据库为目的版本字符集然后再导入。必须对数组类型的设置项进行单独反序列化再使用iconv函数进行字符集转换然后才能序列化入库。遇上数组中还嵌套有数组就更加麻烦了。而如果数组中保存有已经序列化后字符串,那么此数组序列化后就……想着就头大……
故建议新版DZ程序在处理数组字符串化时使用json格式替代serialize序列化入库
- $s = [1, '小众网', 'http://xiaozhong.biz'];
复制代码 其结果分别为
- var_dump(json_encode($s));
- // string(49) "[1,"\u5c0f\u4f17\u7f51","http:\/\/xiaozhong.biz"]"
- var_dump(json_encode($s, JSON_UNESCAPED_UNICODE));
- // string(40) "[1,"小众网","http:\/\/xiaozhong.biz"]"
- var_dump(json_encode($s, JSON_UNESCAPED_SLASHES));
- // string(47) "[1,"\u5c0f\u4f17\u7f51","http://xiaozhong.biz"]"
- var_dump(json_encode($s, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
- // string(38) "[1,"小众网","http://xiaozhong.biz"]"
- PHP5.4.0 options 参数增加常量: JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, 和 JSON_UNESCAPED_UNICODE。
- PHP5.3.3 options 参数增加常量:JSON_NUMERIC_CHECK。
复制代码 虽然在不同参数下json_encode()的结果会不同,但无论哪种json_encode结果作为json_decode()的输入其解码的结果却是唯一的
- array (
- 0 => 1,
- 1 => '小众网',
- 2 => 'http://xiaozhong.biz',
- )
复制代码 如此非常方便对数据进行各种处理,比如迁移、升级、转换字符集
虽然在速度上json_encode/json_decode要比serialize/unserialize慢一些,但dz的缓存机制使得这种性能差别微乎其微——因为缓存中保存的数据都是解码后数组而不是需要反序列化的字符串
|