2011-04-24 116 views
2

我在嘗試使用PHP反序列化數組時遇到了一些問題。序列化/反序列化PHP數組

我有一個類兩種方法,一種用於處理儲存在MySQL表的序列化陣列和一個進行檢索。

我執行第二方法時得到以下錯誤(檢索/反序列化時):

注意:反序列化():錯誤偏移量50647的50623字節/用戶/ benwaine /的NetBeansProjects/SentimentEngineMk2/lib中/TSE/Mapper/Filter.php第39行上

的字符串被存儲在MySQL INA blob字段。該數組是多維的,由一個帶有浮點數組的標記組成。問題是間歇性的,也許表明問題與令牌有關?

 

// Structure 

keywordA - 0.234 
     - 0.234 
KeywordB - 0.23 
     - 0.47 


 

// Methods 

    public function insertFilterForKeyword($id, array $filterProbs) 
    { 

     $sql = "INSERT INTO filter (keyword_id, filter_probs, sample_size_pos, sample_size_neg) 
       VALUE (:id, :filterProbs, :pos, :neg)"; 

     $stmt = $this->pdo->prepare($sql); 

     $meta = array_shift($filterProbs); 

     $stmt->bindParam(':id', $id); 
     $stmt->bindParam(':filterProbs',serialize($filterProbs)); 
     $stmt->bindParam(':pos', $meta['sample_size_pos']); 
     $stmt->bindParam(':neg', $meta['sample_size_neg']); 

     $result = $stmt->execute(); 

     return $result; 
    } 


    public function getFilterByKeyword($keyword) 
    { 
     $sql = 'SELECT f.id, f.keyword_id, f.filter_probs, f.sample_size_pos, f.sample_size_neg 
       FROM filter f 
       JOIN keyword k ON k.id = f.keyword_id 
       WHERE k.keyword = :keyword'; 

     $stmt = $this->pdo->prepare($sql); 

     $stmt->bindParam(':keyword', $keyword); 

     $result = $stmt->execute(); 

     $data = $stmt->fetch(PDO::FETCH_ASSOC); 

     $probArray = unserialize($data['filter_probs']); 

     $filter = new TSE_Filter($probArray); 

     return $filter; 
    } 

我猜誤差與數據中的字符所造成反序列化的問題做。

谷歌搜索後,我試過的方法通過以下方式反序列化線,其中沒有工作:

1)BASE64_ENCODE /解碼序列化的字符串。

 

    //to safely serialize 
    $safe_string_to_store = base64_encode(serialize($multidimensional_array)); 

    //to unserialize... 
    $array_restored_from_db = unserialize(base64_decode($encoded_serialized_string)); 

2)使用預浸比賽改變潛在的困難字符:

 
    unserialize(preg_replace('/;n;/', ';N;', strtolower($data['filter_probs']))); 

任何幫助,將不勝感激!

謝謝。

+0

您可以發佈一個示例,說明當您從數據庫查詢序列化數據而不嘗試反序列化它時,它是什麼樣的? – 2011-04-24 00:49:52

回答

1

I'd've的分貝是問題的〜應變的猜測長度。如果在將數據從數據庫中提取出來後再次輸出序列化字符串,會發生什麼情況?它看起來像一個完成的字符串還是它打破?我認爲blob是大約65k個字符,你可以嘗試將它改爲longblob然後重新保存數據?

另外,如果你有一個,你知道不工作,跳過數據庫保存,並嘗試unserialise字符串立竿見影。那麼至少你知道這個問題是否是反序列化,或者你的數據庫中的數據?

+0

謝謝道格拉斯。你在哪裏正確。在改爲長時間之後,非序列化就成了一種享受。在數據庫保存之前和之後,我最終將字符串寫入文件,然後對它們進行區分,很容易看到您提到的切斷。乾杯! – 2011-04-24 12:37:36

1

在你的示例代碼,你在序列化的字符串使用urlencode。當您反序列化時,您沒有解碼urlencoding,這會導致非序列化失敗。

也許這就是問題所在?

(你應該能夠存儲序列化的數據,而不URL編碼)

+0

感謝您回覆賈尼。在發佈之前,我無意中將其留在了我嘗試的解決方案之一。我已經編輯過,並將其從現在的問題中刪除。 – 2011-04-24 00:44:51

0

檢查數據庫方案定義字段filter .filter_probs如果它足夠長的時間,以節省序列化的字符串。

而且可以序列之前和含有相同的值後解序列化驗證所述陣列。

+0

嗨安迪,我檢查了它是'blob'沒有長度值的定義。這足夠嗎? – 2011-04-24 10:00:26

1

我的猜測是它與列,連接或客戶端字符集有關。

http://dev.mysql.com/doc/refman/5.1/en/charset-conversion.html

如果列具有二進制數據類型(BINARY,BLOB),它包含必須使用單字節字符集編碼的所有值(字符集你將列轉換爲)。如果您使用二進制列將信息存儲在多個字符集中,則MySQL無法知道哪些值使用哪個字符集並且無法正確轉換數據。

所以我想嘗試將列設置爲CHARACTER SET BINARY顯式優先。請記住,序列化的字符串包含空字節和其他奇怪的東西,如果你序列化對象(我意識到你沒有這樣做,但誰知道你的數組包含的鍵和值)。

另外,您在準備時沒有將序列化參數標記爲blob,所以PDO可能也會應用某些字符轉換。對於插入,請嘗試使用此:

$stmt->bindParam(':filterProbs', serialize($filterProbs), PDO::PARAM_LOB); 

也許用時取爲好,只是PDOStatement::bindColumn()同樣的方法(和記與PDOStatement::fetch(PDO::FETCH_BOUND)然後取)。