4

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

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

当我想复活这个物体并将它带回来时,我只需反向运行

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

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

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

编辑:

为了澄清这个过程是这样的

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

希望这是有道理的。该问题是间歇性的,并且不容易始终如一地重现。如果我能得到一些特定的错误消息,我会在这里发布以进一步澄清。但是现在我只是想知道序列化的限制是什么来帮助我进一步调试。

4

6 回答 6

5

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

基本上,您的__sleep函数在您调用序列化时被调用,并且__wakeup是在您反序列化时调用的,所以说它是一个数据库连接:在 sleep() 中关闭连接并将连接字符串存储在某处(可能),然后在唤醒时重新连接。

于 2009-08-27T14:51:42.987 回答
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();
    }
}
于 2009-08-27T14:50:55.517 回答
3

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

于 2009-08-27T14:34:17.807 回答
3

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

  1. 确保您的对象中没有任何不受支持的字符格式
  2. 尝试记录正在序列化的对象有多大
于 2009-08-27T14:34:45.840 回答
1

必须和汤姆一起做这个;引用php.net/serialize

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

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

echo '<pre>'; print_r($decodedObject); echo '</pre>';
于 2009-08-27T14:46:36.240 回答
1

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

于 2009-08-27T14:49:38.310 回答