標籤:
unserialize的這個問題是由一個emlog論壇使用者在使用時報錯而發現的
問題表現情況如下:
emlog緩衝的儲存方式是將php的資料對象(數組)序列化(serialize)後以檔案的形式存放,讀取緩衝的時候直接還原序列化(unserialize)緩衝字串即可讀取資料。
我從使用者那裡取到的緩衝的序列化資料為:
a:1:{s:8:"kl_album";a:4:{s:5:"title";s:12:"精彩瞬 間";s:3:"url";s:41:"http://www.kaisay.cn/?plugin=kl_album";s:8:"is_blank";s:7:"_parent";s:4:"hide";s:1:"n";}}
咋一看瞭解序列化的人都會說,這個資料很正常啊,沒什麼問題呢。可是直接把這段字串進行unserialize,返回的值卻是個False;
代碼
var_dump(unserialize(‘a:1:{s:8:"kl_album";a:4:{s:5:"title";s:12:"精彩瞬間";s:3:"url";s:41:"http://www.kaisay.cn/?plugin=kl_album";s:8:"is_blank";s:7:"_parent";s:4:"hide";s:1:"n";}}‘));
運行結果
問題出在哪裡呢?答案是 s:41:"http://www.kaisay.cn/?plugin=kl_album"
序列化字串中標定該字串http://www.kaisay.cn/?plugin=kl_album的長度是41,可是我們自己數一下卻只有37個字元。就是因為這個問題,導致php還原序列化字串失效。
如果將字串長度改成37,那麼程式就會順利的還原序列化
代碼:
var_dump(unserialize(‘a:1:{s:8:"kl_album";a:4:{s:5:"title";s:12:"精彩瞬 間";s:3:"url";s:37:"http://www.kaisay.cn/?plugin=kl_album";s:8:"is_blank";s:7:"_parent";s:4:"hide";s:1:"n";}}‘));
通過google後才發現,這個問題國外已經很多的網友遇到了,在官方手冊unserialize函數頁面的評論中就有很多網友在討論和研究這個問題的解決方案。
這種情況發生的原因有多種可能,最大的可能就是在序列化資料的時候的編碼和還原序列化時的編碼不一樣導致字串的長度出現偏差。例如資料庫編碼latin1和UTF-8字元長度是不一樣的。
總結:解決方案:
情況一:UTF-8
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);}
情況二:ASC
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);}
php函數unserialize資料返回false問題分析