问题
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.
回答1:
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.
回答2:
@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();
}
}
回答3:
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.
回答4:
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.
- Make sure that you don't have any unsupported character formats in your objects
- Try and log how big the objects are that are being serialized
回答5:
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>';
回答6:
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.
来源:https://stackoverflow.com/questions/1341494/what-could-cause-a-failure-in-php-serialize-function