简体   繁体   English

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

[英]What could cause a failure in PHP serialize function?

I have some serverside PHP code that attempts persist a data object (essentially an multi-dimensional array) to a backend database. 我有一些服务器端PHP代码尝试将数据对象(实质上是一个多维数组)持久存储到后端数据库。 This data object originally comes in as AMF actionscript object sent from a flex application. 此数据对象最初是作为从Flex应用程序发送的AMF actionscript对象引入的。 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. 我想要将整个对象持久化以供以后使用,所以我使用了php serialize函数并将对象编码为一个可以进入数据库字段的简单字符串。 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. 但有时我的PHP脚本失败。 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? 从理论上讲,我的问题是什么可能导致php序列化和编码过程失败? Are there certain characters or kinds of data in the data object array that could cause the serialization to bork? 数据对象数组中是否存在某些可能导致序列化为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. 我有一个Flex / Actionscript客户端应用程序,它将基于AMF的actionscript对象发送到服务器。 On the PHP side I am using the Zend AMF library to read the AMF data. 在PHP方面,我使用Zend AMF库来读取AMF数据。 The object can be inspected in PHP and basically looks like an associative multi-dimensional array. 该对象可以在PHP中检查,基本上看起来像一个关联的多维数组。 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. 正是在这一点上,我尝试序列化和基础64编码对象,以便我可以将对象作为编码字符串持久保存到数据库。

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. 但是现在我只是想知道序列化的限制是什么来帮助我进一步调试。

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 . 避免此问题的一种方法是使用魔术方法: __sleep__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. 基本上,当你调用serialize时会调用__sleep函数,而当你反序列化时会调用__wakeup ,所以说它是数据库连接:在sleep()中关闭连接并将连接字符串存储在某处(可能),并在唤醒时重新连接。

@Greg is correct in that you cannot serialize resources. @Greg是正确的,因为你无法序列化资源。

Given that you describe your objects as "Data objects" I have a feeling that they contain your database connection resources? 鉴于您将对象描述为“数据对象”,我感觉它们包含您的数据库连接资源? (eg $object->rs = mysql_connect(...); ). (例如$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). 如果是这样 ,请考虑在数据对象中使用__sleep()__wakeup()函数__sleep()在序列化之前立即调用__sleep() ,在反序列化之后立即调用__wakeup() )。

The __sleep() function should close any database or file resources while the __wakeup() function should reconnect to the database. __sleep()函数应关闭所有数据库或文件资源,而__wakeup()函数应重新连接到数据库。

The PHP manual entry I linked above has an example of a class that manages a DB connection that is serializeable: 我上面链接的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();
    }
}

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. 您也无法序列化内置的PHP对象,但我不确定它涵盖的是什么。

On php.net/bas64_decode there is some mention of large strings not decoding well. 在php.net/bas64_decode上有一些提到大字符串不能很好地解码。 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 尝试并记录序列化对象的大小

Gotta go with Tom on this one; 要和汤姆一起去这个; to quote php.net/serialize : 引用php.net/serialize

The value to be serialized. 要序列化的值。 serialize() handles all types, except the resource-type. serialize()处理除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. 记录base64_encoding / decoding之后获得的数据,然后使用以下行检查数据。

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

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. Base64编码增加了大约1.3倍的字符串长度,这将在某些数据库系统上被截断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM