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

发布于 2024-08-03 01:31:16 字数 893 浏览 9 评论 0原文

我有一些服务器端 PHP 代码,尝试将数据对象(本质上是多维数组)保存到后端数据库。该数据对象最初作为从 Flex 应用程序发送的 AMF 动作脚本对象出现。我想保留整个对象以供以后使用,因此我使用了 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 编码,以便可以将对象作为编码字符串持久保存到数据库中。

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

I have some serverside PHP code that attempts persist a data object (essentially an multi-dimensional array) to a backend database. This data object originally comes in as AMF actionscript object sent from a flex application. I want persist the object in whole for later use so I have used the php serialize function and encode the object down a simple string that can go into a database field. The code looks like this:

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

When I want to revivify this object and bring it back I simply run the reverse

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

So far this seems to work well. But sometimes my php script fails. I think it is failing at the serialization step. My question is theoretically speaking what could cause a php serialization and encoding process to fail? Are there certain characters or kinds of data in the data object array that could cause the serialization to bork?

Do I need to do some massaging of the data object before I try to serialize it?

Edit:

To clarify the process works like this

I have a Flex/Actionscript client app that sends AMF based actionscript objects to the server. On the PHP side I am using the Zend AMF library to read the AMF data. The object can be inspected in PHP and basically looks like an associative multi-dimensional array. It is at this point that I attempt to serialize and base 64 encode the object so that I can persist the object to the database as a encoded string.

Hopefully this makes sense. The problem is intermittent and not so easy to reproduce consistently. If I can get some specific error messages I will post them here for further clarification. But for now I was just wondering what are the limits of serialization to help me further debug.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

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

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

Resources can't be serialized which might be the problem. A way to avoid this problem is to use the magic methods: __sleep and __wakeup.

Basically, your __sleep function is called when you call serialize, and __wakeup is for when you unserialize, so say it's a database connection: in sleep() close the connection and store the connection string somewhere (perhaps), and in wakeup, reconnect.

秋日私语 2024-08-10 01:31:16

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

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

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

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

@Greg is correct in that you cannot serialize resources.

Given that you describe your objects as "Data objects" I have a feeling that they contain your database connection resources? (e.g. $object->rs = mysql_connect(...);).

If so, consider using __sleep() and __wakeup() functions in your data objects (__sleep() is called immediately before serialization, __wakeup() immediately after de-serialization).

The __sleep() function should close any database or file resources while the __wakeup() function should reconnect to the database.

The PHP manual entry I linked above has an example of a class that manages a DB connection that is serializeable:

<?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();
    }
}
意中人 2024-08-10 01:31:16

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

You can't properly serialize resources, such as file handles or database connections.
You also can't serialize built-in PHP objects, though I'm not exactly sure what that covers.

难得心□动 2024-08-10 01:31:16

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

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

On php.net/bas64_decode there is some mention of large strings not decoding well. Also, if you have unsupported character formats in the object it may cause problems.

  1. Make sure that you don't have any unsupported character formats in your objects
  2. Try and log how big the objects are that are being serialized
羞稚 2024-08-10 01:31:16

这件事必须和汤姆一起去;引用 php.net/serialize

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

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

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

Gotta go with Tom on this one; to quote php.net/serialize:

The value to be serialized. serialize() handles all types, except the resource-type. You can even serialize() arrays that contain references to itself. Circular references inside the array/object you are serializing will also be stored. Any other reference will be lost.

As far as standard objects are concerned you shouldn't have a problem. Log the data you're getting after base64_encoding/decoding, then use the following line to check your data.

echo '<pre>'; print_r($decodedObject); echo '</pre>';
眼藏柔 2024-08-10 01:31:16

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

Are you storing the serialized data inside a database? If so, is the field large enough to hold the data? Base64 encoding adds about 1.3 times to the length of the string which would be truncated on some DB systems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文