直击php中unserialize返回false的解决方法

本文实例讲述了PHP中unserialize返回false的解决方法分享给大家供大家参考。具体方法如下:

PHP 提供serialize(序列化) 与unserialize(反序列化)方法
使用serialize序列化后,再使用unserialize反序列化就可以获取原来的数据。

先来看看如下程序实例:

<?PHP 
$arr = array( 
  'name' => 'fdipzone', 
  'gender' => 'male' 
); 
 
$str = serialize($arr); //序列化 
echo 'serialize str:'.$str.\r\n\r\n; 
 
$content = unserialize($str); // 反序列化 
echo unserialize str:\r\n; 
var_dump($content); 
?>

输出

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

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

<?PHP 
$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;}'; 
var_dump(unserialize($str)); // bool(false) 
?>

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

s:5:url
s:29:http://www.baidu.com/test.html
这两处应为
s:3:url
s:30:http://www.baidu.com/test.html

出现这种问题的原因是序列化数据时的编码与反序列化时的编码不一致导致,例如数据库latin1和UTF-8字符长度不一样。
另外有可能出问题的还有单双引号,ascii字符\0被解析为 '\0',\0在C中是字符串的结束符等于chr(0),错误解析后算了2个字符。
\r在计算长度时也会出问题。

解决方法如下:

// utf8 
function mb_unserialize($serial_str) { 
  $serial_str= preg_replace('!s:(\d+):(.*?);!se', 's:'.strlen('$2').':\$2\;', $serial_str ); 
  $serial_str= str_replace(\r, , $serial_str); 
  return unserialize($serial_str); 
} 
 
// ascii 
function asc_unserialize($serial_str) { 
  $serial_str = preg_replace('!s:(\d+):(.*?);!se', 's:.strlen($2).:\$2\;', $serial_str ); 
  $serial_str= str_replace(\r, , $serial_str); 
  return unserialize($serial_str); 
}

例子:

echo '<Meta http-equiv=content-type content=text/html; charset=utf-8>'; 
 
// utf8 
function mb_unserialize($serial_str) { 
  $serial_str= preg_replace('!s:(\d+):(.*?);!se', 's:'.strlen('$2').':\$2\;', $serial_str ); 
  $serial_str= str_replace(\r, , $serial_str); 
  return unserialize($serial_str); 
} 
 
$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;}'; 
 
var_dump(unserialize($str));  // false 
 
var_dump(mb_unserialize($str)); // 正确

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

使用unserialize:

bool(false)

使用mb_unserialize

array(9) { 
 [time]=> 
 int(1405306402) 
 [name]=> 
 string(6) 新晨 
 [url]=> 
 string(1) - 
 [word]=> 
 string(1) - 
 [rpage]=> 
 string(30) http://www.baidu.com/test.html 
 [cpage]=> 
 string(1) - 
 [ip]=> 
 string(15) 117.151.180.150 
 [ip_city]=> 
 string(31) 中国北京市 北京市移动 
 [miao]=> 
 string(1) 5 
}

相关学习推荐:PHP编程从入门到精通

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...