有个业务需求需要把格式化的数据(有中文)存入到数据表中,起初想起里用的json_encode(),随手拈来的函数。可是想起来中文被它格式化存入数据表中,mysql会自动去掉\u的反斜线。等数据取出在decode的时候 又得重新添加,而且会出现误添加,导致错误。后来想起来serialize()和unserialize(),然后还有他们的一个坑。
数据封装在utf-8编码下进行,因此示例数据如下:
a:3:{i:76969;s:12:"山东省的";i:79255;s:6:"试试";i:79256;s:0:"";}
可以看到utf-8下面单个中文字符占用3个字节,所以s对应的值分别是12,6,0;
然后从库里面拿出这段数据放在本地测试,页面编码默认ANSI,然后就会发现unserialize 报如下错误:
Notice: unserialize(): Error at offset 27 of 66 bytes
然后就是false。然后搜了很多资料才发现,unserialize去反序列化时,会先判断里面字符的长度,然后跟s进行对比,如果对比成功就会解析成功,否则就会报错。
所以如果解析页面的编码跟序列化页面编码不一致的话,就会导致unserialize时strlen的判断和s值不一致,导致错误。
解决办法:
1.统一页面编码;
2.找到一个通用的函数:
原理是重新计算字符的长度,然后替换掉s的值
function common_unserialize($str) {
if(empty($str)){
return '';
}
$str= preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $str );
$str= str_replace("\r", "", $str);
return unserialize($str);
}