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在計算長度時也會出問題。
解決方案如下:
// utf8function 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);}// asciifunction 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">';// utf8function 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)); // falsevar_dump(mb_unserialize($str)); // 正確
使用處理過單雙引號,過濾\r的mb_unserialize方法就能成功還原序列化了。
使用unserializebool(false)使用mb_unserializearray(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 unserialize 返回false的解決方案,更多相關內容請關注php中文網。
相關推薦:
如何通過php 根據字串產生對應數組的方法
關於JSON字串key缺少雙引號的解決方案 的講解
如何通過curl 來擷取 https的 要求方法