2011-04-24 169 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)然后取)。