什么可能导致PHP序列化功能失败?

时间:2009-08-27 14:29:34

标签: php serialization persistence amf

我有一些服务器端PHP代码尝试将数据对象(实质上是一个多维数组)持久存储到后端数据库。此数据对象最初是作为从Flex应用程序发送的AMF actionscript对象引入的。我想要将整个对象持久化以供以后使用,所以我使用了php serialize函数并将对象编码为一个可以进入数据库字段的简单字符串。代码如下所示:

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

当我想要恢复此对象并将其恢复时,我只需运行反向

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

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

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

修改

澄清这个过程是这样的

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

希望这是有道理的。这个问题是间歇性的,不容易一致地重现。如果我能得到一些具体的错误消息,我会在这里发布以便进一步说明。但是现在我只是想知道序列化的限制是什么,以帮助我进一步调试。

6 个答案:

答案 0 :(得分:5)

资源无法序列化,这可能是问题所在。避免此问题的一种方法是使用魔术方法:__sleep and __wakeup

基本上,当您调用serialize时调用__sleep函数,而反序列化时调用__wakeup,所以说它是数据库连接:在sleep()中关闭连接并存储连接字符串某处(也许),并在醒来时重新连接。

答案 1 :(得分:4)

@Greg是正确的,因为你无法序列化资源。

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

如果,请考虑在数据对象中使用__sleep() and __wakeup()函数(在序列化之前立即调用__sleep(),在反序列化之后立即调用__wakeup()。)< / p>

__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();
    }
}

答案 2 :(得分:3)

您无法正确序列化资源,例如文件句柄或数据库连接。 你也无法序列化内置的PHP对象,虽然我不确定它涵盖了什么。

答案 3 :(得分:3)

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

  1. 确保对象中没有任何不受支持的字符格式
  2. 尝试并记录被序列化的对象的大小

答案 4 :(得分:1)

要和汤姆一起去这个;引用php.net/serialize

  

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

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

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

答案 5 :(得分:1)

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