2009-08-27 135 views
2

我有一些服务器端的PHP代码,试图将数据对象(实质上是一个多维数组)存储到后端数据库。该数据对象最初是作为从Flex应用程序发送的AMF动作对象来的。我希望坚持整个对象以备后用,所以我使用了php序列化函数,并将对象编码为一个可以进入数据库字段的简单字符串。代码如下所示:什么可能导致PHP序列化函数失败?

$serializedDataObject = base64_encode(serialize($objectInstance->myDataObject)); 

当我想复活该对象,并把它带回我只需运行反向

$unserializedDatanObject = unserialize(base64_decode($serializedDataObject)); 

到目前为止,这似乎运作良好。但有时我的PHP脚本失败。我认为它在序列化步骤中失败了。我的问题是从理论上讲,可能导致php序列化和编码过程失败的原因是什么?数据对象数组中是否存在可能导致序列化出现的特定字符或种类的数据?

在我尝试序列化之前,是否需要对数据对象进行一些按摩?

编辑:

要澄清的过程是这样的

我发送基于AMF ActionScript对象到服务器的Flex /的ActionScript客户端应用程序。在PHP方面,我使用Zend AMF库来读取AMF数据。该对象可以在PHP中检查,基本上看起来像一个关联的多维数组。正是在这一点上,我试图序列化和基地64编码对象,以便我可以持久对象到数据库作为编码的字符串。

希望这是有道理的。问题是间歇性的,不容易一致地重现。如果我能得到一些特定的错误信息,我会在这里发布它们以供进一步澄清。但是现在我只是想知道序列化的局限性,以帮助我进一步调试。

+1

脚本是否因特定错误/异常而失败?打开错误级别并确保display_errors已打开。 – Ian 2009-08-27 14:31:47

+0

是的,我已经开启了报告,但错误信息对我来说有点神秘。奇怪的是,大部分时间都是这样。数据对象不是太复杂,整数,字符串,布尔值和日期。从我可以告诉它因为时间戳的一些变化而失败。换句话说,当对象被保存似乎是问题的根源。 – 2009-08-27 14:40:00

+0

如果您发布了错误消息,我们可能会解密它 – Greg 2009-08-27 14:41:13

回答

3

您无法正确序列化资源,例如文件句柄或数据库连接。 您也不能序列化内置的PHP对象,但我不完全确定涵盖的内容。

+0

他在base64对它们进行编码之前在对象上调用serialize()。我很确定你可以做到这一点。如果我没有记错,我想我有一些生产代码正在做这件事,并正确处理它。但不是那么base64编码它。 http://us.php.net/serialize – 2009-08-27 14:38:11

+0

你可以序列化几乎任何东西,包括内置的PHP对象(它们仍然是对象,只是由核心提供)。但是,你是正确的,你不能序列化资源。由于OP引用的数据对象不是序列化的,我有一种感觉,说对象包含连接资源给DB。 – dcousineau 2009-08-27 14:42:23

+0

我确实记得不能序列化一个RecursiveIteratorIterator,但似乎现在已经修复了 - 无论如何我的简单测试 – Greg 2009-08-27 14:48:16

3

在php.net/bas64_decode上有一些提到的大字符串解码不好。另外,如果对象中不支持字符格式,则可能会导致问题。

  1. 确保你没有任何不支持的字符格式在你的对象
  2. 尝试登录的对象有多大是正在连载
1

得与汤姆走在这条之一;引用php.net/serialize

要序列化的值。 serialize()处理除资源类型以外的所有类型。你甚至可以序列化()包含自身引用的数组。您正在序列化的数组/对象内的循环引用也将被存储。任何其他参考将会丢失。

就标准对象而言,您应该没有问题。记录您在base64_encoding/decoding之后获得的数据,然后使用以下行检查您的数据。

echo '<pre>'; print_r($decodedObject); echo '</pre>'; 
1

您是否将序列化数据存储在数据库中?如果是这样,是足够大的领域来保存数据? Base64编码增加了大约1.3倍的字符串长度,在某些数据库系统上会被截断。

+0

这个字段应该足够长的例子。我将它设置为longvarchar(在MySQL中)。那里应该使用更长的字段类型? 但大多数情况下,我的脚本的作品。而且大多数对象的大小相同,所以我不认为问题是保存到数据库。我认为它在序列化或编码时失败。 – 2009-08-27 15:08:47

+0

你知道数据是插入数据库还是事先发生故障?为什么不尝试写一个遍历所有记录的简单迭代器来解码和取消序列化数据并查找错误(base64_decode和un-serialize都会在失败时返回false)。 另外我正在检查serialize和un-serialize的bug,并发现在certian版本和certian OS上存在一些问题。发布您正在使用的PHP版本和操作系统可能有助于确定这些错误是否是罪魁祸首。 – MANCHUCK 2009-08-27 15:17:46

+0

也尝试使用文本字段来存储数据。这应该足够长以存储数据。 – MANCHUCK 2009-08-27 15:26:42

4

@Greg是正确的,你不能序列化资源。

鉴于您将对象描述为“数据对象”,我有一种感觉,他们包含您的数据库连接资源? (例如$object->rs = mysql_connect(...);)。

如果是这样,考虑在你的数据对象使用__sleep() and __wakeup()功能(__sleep()被称为立即串行化之前,__wakeup()后立即反序列化)。

__sleep()函数应关闭任何数据库或文件资源,而__wakeup()函数应重新连接到数据库。

PHP手册进入我上面链接有一个管理一个数据库连接是可序列化类的例子:

<?php 
class Connection { 
    protected $link; 
    private $server, $username, $password, $db; 

    public function __construct($server, $username, $password, $db) 
    { 
     $this->server = $server; 
     $this->username = $username; 
     $this->password = $password; 
     $this->db = $db; 
     $this->connect(); 
    } 

    private function connect() 
    { 
     $this->link = mysql_connect($this->server, $this->username, $this->password); 
     mysql_select_db($this->db, $this->link); 
    } 

    public function __sleep() 
    { 
     return array('server', 'username', 'password', 'db'); 
    } 

    public function __wakeup() 
    { 
     $this->connect(); 
    } 
} 
5

资源不能被序列化,这可能是问题。避免这个问题的方法是使用神奇的方法:__sleep and __wakeup

基本上,当你调用系列化你__sleep函数被调用,并且__wakeup是当你反序列化的,所以说这是一个数据库连接:在睡眠()关闭连接和地方存储连接字符串(也许),并在唤醒,重新连接。

相关问题