[php] serialize()/unserialize() 陣列文字序列化 - 資料庫儲存陣列的方式

序列化,反序列化方式

前言

當你有一組陣列資料,是否可以儲存進資料庫文字欄位中呢?
答案是可以的。

『序列化(Serialization)』就是將數據結構或對象狀態轉換為可以存儲的格式的過程。
例如有一個原始陣列數組:

<?
$my_array_data = array('hello', 'world');
//然後如何儲存進入資料庫?

接著使用serialize()這個方式:

<?php
$my_array_data = array('hello', 'world');
$serialize_result = serialize($my_array_data);
你將會得到這個結果:
a:2:{i:0;s:5:"hello";i:1;s:5:"world";}

這邊紀載的資訊意思為:
  • a:2:有一個長度為2的陣列(array)。
  • i:0:陣列中的第一個項目具有一個值為0的整數。
  • s:5:該項目的值“hello”是一個長度為5個字符的字符串。
  • i:1:數組中的第二個項目具有一個值為1的整數值。
  • s:5:該項目的值“world”是一個長度為5個字符的字符串。



等等,甚麼是陣列中的第一個項目具有一個值為0的整數?
其實,若你執行 print_r(array('hello', 'world'));  就可以發現輸出結果為:Array ( [0] => hello [1] => world ),其實還帶有前方的KEY值 0 跟 1 。而 hello 跟 world 則分別是其中的value值。


不過事情有這麼簡單嗎?
尤其是在 UTF-8 情況下,當序列化資料中的字符串計數與保存的字符串的長度不匹配時,就可能會發生非排序偏移錯誤。所以在上面的例子中就會變成這樣:
a:2:{i:0;s:4:"hello";i:1;s:5:"world";}  //不是我們要的結果!!!
注意數字從原本的5變成4個字符,發生偏移了。

當php序列化數據時,會把外部字符存儲為一個雙倍的長度,但是當它傳遞給MySQL時,當表格格式化為UTF-8時,資料庫會將字符轉換為"?",然後將其存儲為單個字符。 但是序列化長度沒有更新,所以當你去unserialize()後的數據會發生偏移的錯誤。
 

解決 serialize 在 UTF-8 環境下儲存問題

最簡潔的是在序列化數據之後使用 base64_encode()函數。
這將防止數據被破壞,因為 base64 可將數據轉換為ASCII,使得在任何排序規則下都可以執行。

所以最安全的方式便是使用以下方式。

serialize序列化資料然後除存進資料庫
<?php
$my_array_data = array('hello', 'world');
$寫入欄位的資料 = base64_encode(serialize($my_array_data));

unserialize 反序列化,從資料庫取出資料使用

<?php
$array_restored_from_db = unserialize(base64_decode($從資料庫取出的資料));
//print_r($array_restored_from_db);

簡易判斷資料庫欄位

原理:判斷前兩碼是否為 a: 開頭。
<?php
$field = $row->$filed; //從資料庫取得的欄位值

if( substr($field ,0 , 2) == 'a:' ){ 
  //原始serialize字元

}else{
  //已經過處理的字元
  
}




 

例外處理


如果你在先前資料庫中就已經存在錯誤的資料,在反序列化會得到以下錯誤:
‘Notice: unserialize() [function.unserialize]: Error at Offset’ error. 
然後,將無法取回資料。
你可用這樣的方式更正資料:

<?php
$fixed_serialized_data = preg_replace_callback ( '!s:(\d+):"(.*?)";!',
    function($match) {
        return ($match[1] == strlen($match[2])) ? $match[0] : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
    }, $error_serialized_data 
);
這可以搜索字符串,重新計算長度,並用正確的值替換字符串長度。不過,它無法恢復原來的外來字符,但至少其餘的數據將加載。

 

參考線上工具

http://www.unserialize.com/


 

回上一頁

相關文章:

喜歡這篇文章嗎?立即分享

Posted : / Views: 452
Last updated :2017-11-18