当前位置:
首页 > 技术 > php unserialize 返回false的解决方法

php unserialize 返回false的解决方法

 

php 提供serialize(序列化) 与unserialize(反序列化)方法。

使用serialize序列化后,再使用unserialize反序列化就可以获取原来的数据。

  1. <?php
  2. $arr = array(
  3.     'name' => 'fdipzone',
  4.     'gender' => 'male'
  5. );
  6. $str = serialize($arr); //序列化
  7. echo 'serialize str:'.$str."\r\n\r\n";
  8. $content = unserialize($str); // 反序列化
  9. echo "unserialize str:\r\n";
  10. var_dump($content);
  11. ?>

输出:

  1. serialize str:a:2:{s:4:"name";s:8:"fdipzone";s:6:"gender";s:4:"male";}
  2. unserialize str:
  3. array(2) {
  4.   ["name"]=>
  5.   string(8) "fdipzone"
  6.   ["gender"]=>
  7.   string(4) "male"
  8. }

但下面这个例子反序列化会返回false

  1. <?php
  2. $str = 'a:9:{s:4:"time";i:1405306402;s:4:"name";s:6:"新晨";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"http://www.baidu.com/test.html";s:5:"cpage";s:1:"-";s:2:"ip";s:15:"117.151.180.150";s:7:"ip_city";s:31:"移动";s:4:"miao";s:1:"5";}';
  3. var_dump(unserialize($str)); // bool(false)
  4. ?>

检查序列化后的字符串,发现出问题是在两处地方

s:5:"url"

s:29:"http://rainyin.com/test.html"

这两处应为

s:3:"url"

s:30:"http://rainyin.com/test.html"

 

出现这种问题的原因是序列化数据时的编码与反序列化时的编码不一致导致,例如数据库是latin1和UTF-8字符长度不一样。

另外有可能出问题的还有单双引号,ascii字符"\0"被解析为 '\0',\0在C中是字符串的结束符等于chr(0),错误解析后算了2个字符。

\r在计算长度时也会出问题。

 

解决方法如下:

  1. // utf8
  2. function mb_unserialize($serial_str) {
  3.     $serial_str= preg_replace('!s:(\d+):"(.*?)";!se'"'s:'.strlen('$2').':\"$2\";'"$serial_str );
  4.     $serial_strstr_replace("\r"""$serial_str);
  5.     return unserialize($serial_str);
  6. }
  7. // ascii
  8. function asc_unserialize($serial_str) {
  9.     $serial_str = preg_replace('!s:(\d+):"(.*?)";!se''"s:".strlen("$2").":\"$2\";"'$serial_str );
  10.     $serial_strstr_replace("\r"""$serial_str);
  11.     return unserialize($serial_str);
  12. }

例子:

  1. echo '<meta http-equiv="content-type" content="text/html; charset=utf-8">';
  2. // utf8
  3. function mb_unserialize($serial_str) {
  4.     $serial_str= preg_replace('!s:(\d+):"(.*?)";!se'"'s:'.strlen('$2').':\"$2\";'"$serial_str );
  5.     $serial_strstr_replace("\r"""$serial_str);
  6.     return unserialize($serial_str);
  7. }
  8. $str = 'a:9:{s:4:"time";i:1405306402;s:4:"name";s:6:"新晨";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"http://www.baidu.com/test.html";s:5:"cpage";s:1:"-";s:2:"ip";s:15:"117.151.180.150";s:7:"ip_city";s:31:"移动";s:4:"miao";s:1:"5";}';
  9. var_dump(unserialize($str));    // false
  10. var_dump(mb_unserialize($str)); // 正确

使用处理过单双引号,过滤\r的mb_unserialize方法就能成功反序列化了。

  1. 使用unserialize
  2. bool(false)
  3. 使用mb_unserialize
  4. array(9) {
  5.   ["time"]=>
  6.   int(1405306402)
  7.   ["name"]=>
  8.   string(6) "新晨"
  9.   ["url"]=>
  10.   string(1) "-"
  11.   ["word"]=>
  12.   string(1) "-"
  13.   ["rpage"]=>
  14.   string(30) "http://www.baidu.com/test.html"
  15.   ["cpage"]=>
  16.   string(1) "-"
  17.   ["ip"]=>
  18.   string(15) "117.151.180.150"
  19.   ["ip_city"]=>
  20.   string(31) "移动"
  21.   ["miao"]=>
  22.   string(1) "5"
  23. }

 

php unserialize 返回false的解决方法:等您坐沙发呢!

发表评论

您必须 [ 登录 ] 才能发表留言!