• 首页   /  職場   /  
  • php反序列化失敗是因為序列化數據時的編碼與反序列化時的編碼不一致導致的,其解決辦法就是使用處理過的單雙引號,過濾“\r”的“mb_unserialize”方法即可成功反序列化。

    推薦:《PHP視頻教程》

    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
    functiоn 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
    functiоn 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
    functiоn 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)); // 正確

    使用處理過單雙引號,過濾\r的mb_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反序列化失敗怎麼辦的詳細內容!


    ————————————————