首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP unserialize 返回 false 解決方案:編碼不一致導致長度錯誤修復

     編輯:PHP 綜合知識

問題現象

unserialize() 返回 false,且不拋出例外。常見於跨系統、跨資料庫編碼環境序列化/反序列化不一致時。

根本原因

PHP 序列化格式包含字串長度:s:29:"https://example.com"。若序列化時編碼為 UTF-8 (中文 3 位元組),反序列化時環境視為 Latin1 (單位元組),長度計算錯誤導致解析失敗。單雙引號、\0、\r 等特殊字元同理。

修復函數

<?php
// UTF-8 環境修復
function mb_unserialize($serial_str) {
    // 重新計算所有 s:長度:"值" 的實際位元組長度
    $serial_str = preg_replace_callback(
        '!s:(\d+):"(.*?)";!s',
        function($m) { return 's:' . strlen($m[2]) . ':"' . $m[2] . '";'; },
        $serial_str
    );
    $serial_str = str_replace("\r", '', $serial_str);
    return unserialize($serial_str);
}

// ASCII/單位元組環境修復
function asc_unserialize($serial_str) {
    $serial_str = preg_replace_callback(
        '!s:(\d+):"(.*?)";!s',
        function($m) { return 's:' . strlen($m[2]) . ':"' . $m[2] . '";'; },
        $serial_str
    );
    $serial_str = str_replace("\r", '', $serial_str);
    return unserialize($serial_str);
}

測試案例

$bad = 'a:9:{s:4:"time";i:1405306402;s:5:"name";s:6:"新晨";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"https://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($bad));        // bool(false)
var_dump(mb_unserialize($bad));     // 正常陣列

預防最佳實踐

  1. 統一編碼:資料庫、連線、PHP、HTML 全鏈路 UTF-8 ( SET NAMES utf8mb4, default_charset = "UTF-8" )。
  2. 避免手工拼裝序列化字串:永遠使用 serialize() 產生。
  3. 儲存格式改用 JSON:json_encode/json_decode 無長度前綴問題、跨語言相容、可讀性佳。
  4. 若必須用 serialize:在寫入資料庫前 base64_encode(serialize($data)),讀取後 unserialize(base64_decode($str)),繞過編碼轉換層。

結語

unserialize 失敗多因序列化與反序列化環境編碼不一致導致長度前綴錯誤。mb_unserialize 透過正則重算長度可應急修復,但根治之道在於全鏈路 UTF-8 標準化或改用 JSON 格式儲存。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved