|
|
 |
serialize (PHP 3 >= 3.0.5, PHP 4, PHP 5) serialize --
Generates a storable representation of a value
Descriptionstring serialize ( mixed value )
serialize() returns a string containing a
byte-stream representation of value that
can be stored anywhere.
This is useful for storing or passing PHP values around without
losing their type and structure.
To make the serialized string into a PHP value again, use
unserialize(). serialize()
handles all types, except the resource-type.
You can even serialize() arrays that contain
references to itself. References inside the array/object you
are serialize()ing will also be stored.
When serializing objects, PHP will attempt to call the member function
__sleep() prior to serialization. This is to allow the
object to do any last minute clean-up, etc. prior to being serialized.
Likewise, when the object is restored using unserialize()
the __wakeup() member function is called.
Note:
This didn't work correctly until 4.0.7.
Note:
In PHP 3, object properties will be serialized, but methods are
lost. That limitation was removed in PHP 4 as both properties
and methods are now restored. Please see the Serializing Objects
section of Classes and
Objects for more information.
It is not possible to serialize PHP built-in objects.
Example 1. serialize() example |
<?php
$conn = odbc_connect("webdb", "php", "chicken");
$stmt = odbc_prepare($conn,
"UPDATE sessions SET data = ? WHERE id = ?");
$sqldata = array (serialize($session_data), $PHP_AUTH_USER);
if (!odbc_execute($stmt, &$sqldata)) {
$stmt = odbc_prepare($conn,
"INSERT INTO sessions (id, data) VALUES(?, ?)");
if (!odbc_execute($stmt, &$sqldata)) {
}
}
?>
|
|
See Also: unserialize().
User Contributed Notes
serialize
s dot marechal at jejik dot com
04-Feb-2005 06:42
gafunchal NOSPAN at inf dot ufrgs dot br
22-Jan-2005 06:33
(please, excuse my poor English)
'serialize' does strange things with floats, this code:
$a = 3.14;
$s = serialize($a);
$fp = fopen("storage", "w");
fwrite($fp, $s);
fclose($fp);
outputs something like (PHP 5.0.2):
d:3.140000000000000124344978758017532527446746826171875;
I wonder why serialize doesn't store data (not only float, I mean all types of data) in a more 'economic' format. Maybe binary is not the best option (there can be trouble storing it in databases), but there are still a lot of other possibilities.
cjmeyer at npcc dot net
24-Dec-2004 01:16
More on troubles with recursive object references and serialization.
In my PHP 4.2.2 the solution suggested above (by james at gogo dot co dot nz), to pass a reference to the object to serialize(), does not help. There are still multiple copies of the objects woken up, and the recursive reference is no longer recursive.
The only solution I have found is to use the __sleep and __wakeup magic functions to only serialize the link one-way, then recreate it manually on unserialize. This isn't too difficult; here is some code demonstrating this approach:
class A {
var $data = Null;
var $b = Null;
function A($data, $bData) {
$this->data = $data;
$this->b = new B(&$this, $bData);
}
function printData() {
print 'A thinks A data is ' . $this->data . "\n";
print 'A thinks B data is ' . $this->b->data . "\n";
}
function __sleep() {
print "A is going to sleep.\n";
return array('data', 'b');
}
function __wakeup(){
print "A is waking up.\n";
$this->b->reLinkA($this);
}
}
class B {
var $data = Null;
var $a = Null;
function B(&$a, $data) {
$this->a =& $a;
$this->data = $data;
}
function printData() {
print 'B thinks A data is ' . $this->a->data . "\n";
print 'B thinks B data is ' . $this->data . "\n";
}
function __sleep() {
print "B is going to sleep.\n";
return array('data');
}
function __wakeup(){
print "B is waking up.\n";
}
function reLinkA(&$a) {
$this->a =& $a;
}
}
$a = new A("origAdata", "origBdata");
print '<pre>';
print "I think A data is " . $a->data . "\n";
print "I think B data is " . $a->b->data . "\n";
$a->printData();
$a->b->printData();
$serA = serialize($a);
$newA = unserialize($serA);
$newA->data = 'newAdata';
$newA->b->data = 'newBdata';
print "I think new A data is " . $newA->data . "\n";
print "I think new B data is " . $newA->b->data . "\n";
$newA->printData();
$newA->b->printData();
wiart at yahoo dot com
16-Dec-2004 05:40
Warning: on 64 bits machines, if you use a long string only composed of numbers as a key in an array and serialize/unserialize it, you can run into problems:
an example code:
$arr["20041001103319"] = 'test';
var_dump( $arr);
$arr_in_str = serialize($arr);
print "Now result is: $arr_in_str<BR />";
$final_arr = unserialize($arr_in_str);
print "The final unserialized array:<BR />";
var_dump($final_arr);
The result:
array(1) { [20041001103319]=> string(4) "test" }
Now result is: a:1:{i:20041001103319;s:4:"test";}
The final unserialized array:
array(1) { [683700183]=> string(4) "test" }
As you can see, the original array :
$arr["20041001103319"] = "test"
after serialize/unserialize is:
$arr[683700183] = "test"
As you can see, the key has changed ...
Apparently a problem of implicit casting + integer overflow (I posted a PHP bug report: http://bugs.php.net/bug.php?id=31117)
I tested with the latest 4.3.10 compiled on my laptop (32 bits, Mandrake 9.1) --> no such problem. But compiled on AMD 64 bits (Red Hat Taroon), the problem is present.
Hope this will help some of you to not loose almost a whole day of debugging ;-)
richard dot prangnell at ntlworld dot com
12-Dec-2004 04:08
Although the serialise function has its proper uses, it is a relatively slow process. I try to avoid using it wherever possible in the interests of performance. You can store text records in a database as plain text even when it contains PHP variables. The variable values are lost, naturally; but if they can easily be re-attached to retrieved records, zillions of clock cycles can be saved simply by using the str_replace() function:
if($convert)
{
$mainContent = str_replace('$fixPath', $fixPath, $mainContent);
$mainContent = str_replace('$theme', $theme, $mainContent);
}
The above snippet is used in a CMS project. $fixPath contains something like '.' or '..' to prepend relative paths (allowing the record to be used by scripts located in different parts of the directory hierarchy) and $theme inserts the name of the users custom page rendering scheme, which obviously would be undefined at record storage time anyway.
corey at eyewantmedia dot com
08-Dec-2004 12:47
If this helps anybody, I was looking for a few quick calls to cache stuff to files. I settled on the below functions. By the way, if I am doing something stupid here, I'd appreciate some comments on that also. Anyway, on with the code:
First, the usage:
//Use:
$var = tuncache('MyCacheName');
if (is_null($var)) {
$var = 'a really expensive process';
$check = tcache('MyCacheName', $var, '+25 minutes');
if (is_null($check)) {
die('I need to reset my permissions or get a bigger hard drive');
}
}
//use $var now
Now, the functions:
//uses strtotime to decide how long to cache $cacheVar based on $lifespan
//so anything but a timestamp works. +1 day works, 09/14/2010 works, etc
function tcache($cacheName, $cacheVar, $lifespan=null) {
if (!is_null($lifespan)) { //a lifespan was provided
if (strpos($lifespan, '+') === 0 || strpos($lifespan, '-') === 0) {
//Have to do this to counter for bug in php5 to
//properly evaluate now to do the date math
$endTime = strtotime(date('m/d/Y H:i:s') . ' ' .$lifespan);
} else {
//we can safely use anything else I think
$endTime = strtotime($lifespan);
}
} else {
//cache forever (forever being ten years) until manually deleted
$endTime = strtotime(date('m/d/Y H:i:s') . ' +10 years');
}
$cVal = serialize($cacheVar);
$file = tFindcache($cacheName);
$result = true;
$f = fopen($file, 'w');
if ($f === false) {
$result = null; //barf if we can't open the file
} else { //write the cache
fwrite($f, $endTime . "\n");
fwrite($f, $cVal);
fclose($f);
}
return $result;
}
function tuncache($cacheName) {
$file = tFindCache($cacheName);
if (is_readable($file)) {
//open file
$f = fopen($file, 'r');
$time = time();
$expTime = trim(fgets($f));
//check time
if ($time > $expTime) {
//It expired
$result = null;
} else {
//Read it and unserialize it
$data = fread($f, filesize($file));
$result = unserialize($data);
}
} else {
//barf
$result = null;
}
return $result;
}
//just to set a few options for setting where to save stuff
function tFindCache($cacheName) {
if (isset($_ENV['PHP_CACHE_PATH'])) {
$cachePath = $_ENV['PHP_CACHE_PATH'];
} else if (isset($_SERVER['PHP_CACHE_PATH'])) {
$cachePath = $_SERVER['PHP_CACHE_PATH'];
} else {
$cachePath = './'; //Potential danger here
}
$cachePath .= 'PHP_CACHE_' . $cacheName . '.cache';
return $cachePath;
}
01-Dec-2004 03:30
This is just a modification of what Alan Reddan (areddan at silverarm dot ie) posted below.
I figured it would be faster than walking an array, and it works wonderfully with cookies
<?php
$data[qwerty] = "blah";
$data[1][a] = "1aa";
$data[2][b] = "2bb";
$data[3][c] = ";;;;;;";
$data[name][first] = "Bob";
$data[name][last] = "Jones";
$data[val] = "This is a real long test string, to see how well the compression works!";
$string = gzcompress(serialize($data), 9);
setcookie("my_var", $string, time()+60*60*24*60, '/');
if (isset($_COOKIE[my_var])) {
$array = unserialize(gzuncompress($_COOKIE[my_var]));
echo "<pre>";
print_r($array);
echo "</pre>";
}
?>
you can replace gzcompress with base64_encode and gzuncompress with base64_decode to have a similar experience
Alan, thanks for the tip though, it got me where I wanted to be!
paul at moveNOtoSPAMiceland DOT com
18-Nov-2004 10:29
I was trying to submit a serialized array through a hidden form field using POST and was having a lot of trouble with the quotes. I couldn't figure out a way to escape the quotes in the string so that they'd show up right inside the form, so only the characters up to the first set of quotes were being sent.
My solution was to base64_encode() the string, put that in the hidden form field, and send that through the POST method. Then I decoded it (using base64_decode()) on the other end. This seemed to solve the problem.
Alexei dot Filine at cern dot ch
24-Oct-2004 09:57
A simple way to transfer PHP variables between PHP scripts running on different hosts can be done with HTTP_Request PEAR module. I think it is much more fast way than one done with XML-RPC but less portable (there were described ways to exchange vars between Perl and PHP below). Recieved PHP obects are required to be created before recieving by class definition similar to definition used on sending side. A script sending variable must output nothing except data sent by function 'sendVariable' so a 'composite variable' is to be used to transfer some variables by one request.
<?php
ini_set( 'include_path', '.' );
require_once "config.php"; ini_set( 'include_path', ini_get( 'include_path' ).$PEAR_path );
require_once "HTTP/Request.php";
$gzcompressed_serialized_type = 'application/serialized_gzcompressed_PHP_variable';
$serialized_type = 'application/serialized_PHP_variable';
$compression_flag_name = '_compressionFlag_';
header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
header( "Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT" );
function recieveVariable( $url,
&$var,
$user = '',
$passw = '',
$compression_flag = 1 ) {
global $gzcompressed_serialized_type;
global $serialized_type;
$req =& new HTTP_Request( "" );
$req->setURL( $url );
$req->setMethod( HTTP_REQUEST_METHOD_POST );
if ( $user && $passw ) {
$req->addPostData( $user,
$passw );
}
$response = $req->sendRequest();
$req->clearPostData();
if ( $compression_flag ) {
$req->addPostData( $compression_flag_name, 1 );
}
if ( PEAR::isError( $response ) ) {
echo $response->getMessage();
} else {
$header = $req->getResponseHeader();
if ( $req->getResponseCode() != 200 ||
! ( $header['content-type'] == $gzcompressed_serialized_type ||
$header['content-type'] == $serialized_type ) ) {
echo $req->getResponseBody();
} else {
if ( $header['content-type'] == $gzcompressed_serialized_type )
{
$data = gzuncompress( $req->getResponseBody() );
} else {
$data = $req->getResponseBody();
}
$var = unserialize( $data );
return 1;
}
}
return 0;
}
function sendVariable( &$var, $compression_flag = 1 ) {
global $gzcompressed_serialized_type;
global $serialized_type;
header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
header( "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
if ( $compression_flag ) {
header( 'content-type: '.$gzcompressed_serialized_type );
echo gzcompress( serialize( $var ) );
} else {
header( 'content-type: '.$serialized_type );
echo serialize( $var );
}
}
?>
on client side:
<?php
...
require_once "exchange-protocol.php";
...
if (recieveVariable( $url, $var) ) {
} else {
}
?>
on the server side:
<?php
...
require_once "exchange-protocol.php";
...
sendVariable( $var, $compression_flag )
?>
areddan at silverarm dot ie
23-Oct-2004 03:56
<?php
$data[qwerty] = "blah";
$data[1][a] = "1aa";
$data[2][b] = "2bb";
$data[3][c] = ";;;;;;";
array_walk($data,'base64_encoder_multi');
$serialized_string = serialize($data);
$array = unserialize($serialized_string);
array_walk($array,'base64_cleaner_multi');
print_r($array);
function base64_encoder_multi(&$val,$key) {
if (is_array($val)) array_walk($val,'base64_encoder_multi',$new);
else {
$val = base64_encode($val);
}
}
function base64_cleaner_multi(&$val,$key) {
if (is_array($val)) array_walk($val,'base64_cleaner_multi',$new);
else {
$val = base64_decode($val);
}
}
?>
brooklynphil hotmail com
06-Oct-2004 03:07
In my experience of the (far and few in between) times when it is necessary to store large (megabytes) amounts of data in a php-readable ascii file format, using var_export() and require() is much faster serialize() and unserialize(file_get_contents()) (I have tested it on classes encapsulating arrays, i.e. <?php class blah { $a = array(megsofstuffhere); $b = array(megsofstuffhere); $c=... }; $data = new blah ?>) (var_export is also more readable and notepadable than serialize!)
However, since var_export produces only the rvalue (or uninstantiation), of the data needed, dont forget to cosmetically modify output of var_export( , true): in case of classes, you will need to use "$var = new classname" (and rename a possible stdClass) and in case of arrays, etc, just use "$var = ".var_export(). The file being var_export()ed to and require()ed must also be encapculated in "<?php ?>" when written to (or else its just dumped to browser/stdout as a textfile).
Hope this helps :)
--Phil
P.S. (in cases of small amounts of data, serialize is better, especially for cross-URL data transport using <?php base64_encode(gzdeflate(serialize()))?>)
jan at bestbytes dot de
05-Oct-2004 03:58
This should be EXTREMELY helpful when you are getting lost in php 4 circular references and sessions or serializing ...
<?php
class Node {
var $value;
var $child;
var $parent;
var $load;
var $__destroyed = false;
function Node($value)
{
$this->value = $value;
global $load;
$this->load = $load;
}
function setParent(&$parent)
{
$this->parent = &$parent;
}
function setChild(&$child)
{
$this->child = &$child;
}
function __destroy()
{
$props = get_object_vars($this);
foreach($props as $propName => $propValue) {
unset($propValue);
if(is_object($this->$propName)) {
if(method_exists($this->$propName, '__destroy') AND $this->$propName->__destroyed !== false) {
$this->$propName->__destroy();
}
}
if(isset($this->$propName)) {
unset($this->$propName);
}
}
}
}
header('Content-type: text/plain');
$loadSize = 4;
$load = str_repeat('.', $loadSize);
for($i = 0;$i<10;$i++) {
echo '-------------------- '.(memory_get_usage()/1024).' -------------------------'.chr(10);
$serMe = array();
$serMe['parent'] =& new Node('parent');
$serMe['child'] =& new Node('child');
$serMe['parent']->setChild($serMe['child']);
$serMe['child']->setParent($serMe['parent']);
$str = serialize($serMe);
$serMe['parent']->__destroy();
$serMe['child']->__destroy();
$serMe = unserialize($str);
unset($str);
$serMe['parent']->value = 'new parent';
echo '-->'.$serMe['parent']->child->parent->value.chr(10);
echo '-->'.$serMe['parent']->value.chr(10);
$serMe['parent']->__destroy();
$serMe['child']->__destroy();
unset($serMe);
}
?>
mary at nospam dot com
20-Sep-2004 03:57
If you use serialize() to easily convert an array to a sort of string which you can add to a URL, pay attention to the length of the serialized array.
A URL has a limit when it comes to passing variables and values and it cuts off whatever is over limit. If your serialized array is too long, it will be cut off and you will end up with strange results on your other pages.
jasbarne NOSPAM indiana SPAMSUCKS edu
22-Aug-2004 03:01
ignatiev at users dot sourceforge dot net and others using __sleep():
If you decide to add this functionality (for whatever reason) you can serialize a modified copy of the object instead of the original object. There's added overhead of copying, but doing this allows you to continue using the original object after you've serialize it.
goetas at lignano dot it - GoetAs
11-Aug-2004 12:41
the serialize dont function properly when a variable contain a ;
I wrote these two functions that resolve this problem:
this function work only with arrays:
<?php
function base64_unserialize($str){
$ary = unserialize($str);
if (is_array($ary)){
foreach ($ary as $k => $v){
if (is_array(unserialize($v))){
$ritorno[$k]=base64_unserialize($v);
}else{
$ritorno[$k]=base64_decode($v);
}
}
}else{
return false;
}
return $ritorno;
}
function base64_serialize($ary){
if (is_array($ary)){
foreach ($ary as $k => $v){
if (is_array($v)){
$ritorno[$k]=base64_serialize($v);
}else{
$ritorno[$k]=base64_encode($v);
}
}
}else{
return false;
}
return serialize ($ritorno);
}
?>
Andrew dot Morrison at stanford dot edu
29-Jun-2004 05:02
Correction to my last note:
__sleep should return an array only containing the names of instance-variables to serialize.
A simple (if not a little wasteful) hack to serialize all but a few class vars is to use get_class_vars as follows:
<?php
class strawman
{
var $good_var;
var $lame_var;
function __sleep()
{
print "Function __sleep() called\n";
$vars = get_class_vars('strawman');
unset($vars['lame_var']);
return array_keys($vars);
}
function __wakeup()
{
print "Function __wakeup() called\n";
}
function strawman() { }
}
session_start();
if(session_is_registered('strawman'))
{
print("session data:\n");
print_r($_SESSION['strawman']);
session_destroy();
}
else
{
$strawman =& new strawman();
session_register('strawman');
print("new session data:\n");
print_r($_SESSION['strawman']);
}
?>
dr dot slump at cyteknt dot com
27-Apr-2004 11:15
regarding PHP to JS serialization I did some time ago a function which works using "eval" as Harry points out.
<?php
function is_assoc_array( $var ) {
if ( (!is_array($var)) || (!count($var)) ) return false;
foreach($var as $k=>$v)
if (! is_int($k)) return true;
return false;
}
?>
Serialize function which generates JavaScript's eval's compatible code.
Usage (JavaScript) :
var myVar = eval('<?php js_serialize($phpvar); ?>');
Notes:
Objects and associative arrays are encoded as JS Objects
Doesn't serialize object methods
Serializes 'resource' types as nulls
Assoc. Arrays containing integer keys, those keys are prefixed with 'idx_'
<?php
function js_serialize($var, $recursed = false) {
if (is_null($var) || is_resource($var)) return 'null';
$js = '';
if (is_object($var) || is_assoc_array($var)) {
$props = (array)$var;
foreach($props as $k=>$v) {
if (is_int($k)) $k = "idx_$k";
$js .= $k.':'.js_serialize($v, true).',';
}
if (count($props))
$js = substr($js, 0, strlen($js)-1);
$js = '{'.$js.'}';
if (! $recursed) $js = "($js)";
} elseif (is_array($var)) {
foreach($var as $v)
$js .= js_serialize($v, true).",";
if (count($var))
$js = substr($js, 0, strlen($js)-1);
$js = "[$js]";
} elseif (is_string($var)) {
$var = str_replace( array('"', "\n", "\r"), array('\\"', '\\n'), $var );
$js = $recursed ? "\"$var\"" : "(new String(\"$var\"))";
} elseif (is_bool($var)) {
$var = ($var)?'true':'false';
$js = $recursed ? $var : "(new Boolean($var))";
} else { $js = $recursed ? $var : "(new Number($var))";
}
return $js;
}
?>
hfuecks at phppatterns dot com
21-Apr-2004 10:20
Regarding serializing PHP data types to Javascript, following Ivans note below, theres an example at http://www.tekool.net/php/js_serializer/.
The basic serialization looks good although, in its current form, it works on the basis of generating Javascript source which a browser executes as a page loads. Using Javascripts eval() the same can be done with strings containing Javascript if youre working with something like XMLHTTPRequest
Antonie
20-Apr-2004 12:12
Passing of multiple select (single dimensional or even multidimensional) arrays is even harder, even using serialize.
Jouhni [jouhni at web dot de]
08-Feb-2004 07:48
In order to save serialized values in cookies you have to pay attention to the following:
A serialized array looks like this:
a:2:{i:0;s:9:"Element 1";i:1;s:9:"Element 2";}
Because quotation marks are saved with a backslash in front of it in cookies it is not possible to unserialize a cookie-saved serialized array. You have to do a stripslashes() before unserializing the cookie.
info at b1g dot de
07-Feb-2004 12:37
If you are using Cache_Lite from pear.php.net and if you are logging in your users using cookies, use this cache-ID for example:
<?php
$cache_id = base64_encode($_SERVER['REQUEST_URI'] . serialize($_COOKIE));
?>
This will create a new page in cache when a user logs in. Anyway he can't login properly. Works fine for me.
Sorry for my broken English.
tino at infeon dot com
24-Nov-2003 04:20
While writing shopping cart applications i needed a way to keep track of many variables beteween page loads.. i was using a cookie for each but this became hard to manage so I cam up with this simple session object. It serializes the object, base 64 encodes it and sets a cookie for it.. vice versa on page load where it detects the cookie
add whatever variables you need to this class
btw if you like it, hate it or have any comments send me an email to let me know
<?php
class session {
var $cartID;
var $userID;
var $userAuth;
function session () {
if ($_GET['session']) {
$this = unserialize (base64_decode ($_GET['session']));
} else {
if ($_COOKIE['session']) {
$this = unserialize (base64_decode ($_COOKIE['session']));
}
}
}
function save () {
setcookie ('session', base64_encode (serialize ($this)));
}
function delete () {
setcookie ('session');
unset ($this);
}
}
?>
ignatiev at users dot sourceforge dot net
23-Oct-2003 08:35
One problem with serialize() is that by default it does NOT alter the object, so nothing prevents you from continuing using you object after serialize()'ing it.
After a while, you or someone else decides to optimize storage of this object and add a __sleep and __wakeup functions; now, serialize()'ing this same class calls __sleep() member function, potentially changing the object - old code unexpectedly breaks.
Possible solutions: in the above scenario old code would most likely still work if __sleep() only creates new object variables, not altering existing ones. Another option is to always call __wakeup(), if it exists, after each serialize(), or immediately destroy the object if it is no longer used.
iam4webwork at hotmail dot com
14-Sep-2003 07:00
I think an example is in order to specify what is meant by "returns a string containing a byte-stream representation of value that can be stored anywhere."
Here's an example:
<?php
echo serialize("php");
?>
Result is as follows:
s:3:"php";
The cryptic result is a string indicating that the serialized data is itself a string of 3 bytes whose value is "php".
james at gogo dot co dot nz
30-Jul-2003 05:04
I just spent an hour rifling through code to find the cause of a problem
only to find it's an oddity with serialization and recursive objects, so
figured I'd post for the next person who gets the same problem.
********************************* Symptoms *********************************
When unserializing a previously serialized object, the __wakeup() function
is mysteriously called more than once, and the accessing the objects
properties from the "outside" gives different results than accessing them
from an object contained within the object and holding a recursive
reference to the object.
********************************** Example *********************************
<?php
class foo2 {
var $foo = NULL;
function foo2(&$foo) {
$this->foo =& $foo;
}
function fooName() {
echo 'foo2 thinks foo->name is ' . $this->foo->name . '<br>';
}
}
class foo {
var $name = 'unnamed';
var $foo2 = NULL;
function foo() {
$this->foo2 =& new foo2($this);
}
function fooName() {
echo 'foo thinks foo->name is ' . $this->name . '<br>';
}
function __wakeup() {
echo "foo is waking up<br>";
}
}
$myFoo =& new foo();
$myFoo->name = 'myFoo';
echo "I think foo->name is {$myFoo->name}.<br>";
$myFoo->fooName();
$myFoo->foo2->fooName();
$serializedFoo = serialize($myFoo);
$myNewFoo = unserialize($serializedFoo);
$myNewFoo->name = 'myNewFoo';
echo "I think foo->name is {$myNewFoo->name}.<br>";
$myNewFoo->fooName();
$myNewFoo->foo2->fooName();
?>
********************************** Analysis ********************************
execution of the example produces...
I think foo->name is myFoo.
foo thinks foo->name is myFoo
foo2 thinks foo->name is myFoo
foo is waking up
foo is waking up
I think foo->name is myNewFoo.
foo thinks foo->name is myNewFoo
foo2 thinks foo->name is myFoo
We can see that the first three lines are as expected, however we see
__wakeup is happening twice, and then the final line is in error as foo2
apparently does not see the changed name.
What is happening is that there are actually two seperate foo objects being
deserialized, the "top level one" and the one that was originally
referenced in foo2, that is, the reference is not being serialized as a
reference but rather a whole object. This is evident in the two __wakeup()
calls, there are two foo objects being woken up.
******************************** Solution **********************************
The solution is very simple, when serializing it is necessary to force the
passing of a reference to the top-level object being serialized thus..
$serializedFoo = serialize(&$myFoo);
with that form of the serialization (note the ampersand to force passing of
reference), the example produces the following..
I think foo->name is myFoo.
foo thinks foo->name is myFoo
foo2 thinks foo->name is myFoo
foo is waking up
I think foo->name is myNewFoo.
foo thinks foo->name is myNewFoo
foo2 thinks foo->name is myNewFoo
We note now there is only one __wakeup() call being made and that all
parties agree on the name property of the foo object.
******************************** Notes ************************************
I was of the belief that ampersand's in the arguments to functions was
deprecated in favour of ampersands in the function's parameter list
declaration (i.e instead of "blah(&$my_thing)" we declare blah as "function
blah(&$your_thing) {...}"), however this required use of serialize seems to
contravene this deprecation as it is plainly necessary to use the ampersand
in the function call here. Perhaps this is a hold-over from earlier times
and will be changed in the future ?
--
James Sleeman (http://www.gogo.co.nz/)
dan at mojavelinux dot com
18-Jul-2003 02:08
In order to safely unserialize a complex object in any context, it is wise to save two files at the time of serialization (or save the file in two parts). One file will contain the result of get_included_files() at the time of serialization and the other file contains the serialized version of the object. To unserialize, simply read in the included file list and call include_once on all of those files and then call unserialize on your object data.
While this may be slightly inefficient because certain files that were included are no longer needed (maybe they were only needed when creating the object), at least you can be sure the object data is going to come out of serialization okay.
Note: If you stick to the convention of classes beginning with uppercase (and the filenames following the classnames) then you can even filter the get_included_files() list to get only the class definition files.
webmaster at feeltong dot com
12-Jun-2003 05:49
People usually use 'hidden' fields when they submit some variables from previous step to the next step even if they have so many varibles to send. It will look like following form.
<form name='tmpForm' method='post' action='nextStep.php'>
<input type='hidden' name='var[name]' value='<?=$var[name]?>'>
<input type='hidden' name='var[id]' value='<?=$var[id]?>'>
<input type='hidden' name='var[address]' value='<?=$var[address]?>'>
<input type='hidden' name='var[age]' value='<?=$var[age]?>'>
<input type='hidden' name='var[gender]' value='<?=$var[gender]?>'>
<input type='hidden' name='var[car]' value='<?=$var[car]?>'>
.
.
.
</form>
Look at the following codes. It is more simplified. I'd better use base64_encode and serialize than stripslashes and serialize.
<form name='tmpForm' method='post' action='nextStep.php'>
<input type='hidden' name='var' value='<?=base64_encode(serialize($var))?>'>
</form>
Have Fun !!!
rodrigo at ditech dot com dot br
17-Apr-2003 01:38
Hi!
If you wanna save all the POST data and reload it again in another time... you can use this:
(Thanks for my_stripslashes() function ;-)
<?php
if ($REQUEST_METHOD=="POST") {
$fp = fopen("postData.txt","w");
$data = addslashes(serialize($_POST));
fwrite($fp, $data);
fclose($fp);
}
if (file_exists("postData.txt")) {
$data = file("postData.txt");
$data = my_stripslashes($data[0]); $postData = unserialize($data);
extract($postData, EXTR_OVERWRITE);
}
?>
Now you have all variables from old POST in your actual script.
Well useful when you have a great form very used and of course, DEPENDING of your tool.
pli9 at itsa dot ucsf dot edu
01-Feb-2003 01:05
I have also written some code for importing serialized PHP data into PERL and then writing it back into PHP. I think the similar library posted above is actually more robust for a few select cases, but mine is more compact and a little easier to follow. I'd really like comments if anyone finds this useful or has improvements. Please credit me if you use my code.
http://www.hcs.harvard.edu/~pli/code/serialPHP.pm
kjh90 at orgio dot net
20-Mar-2002 02:43
If you want to put serialized data into DB, you have to add slashes.
At this point, there's a problem. If you got data via HTTP POST method, the data has slashes already. I tried to work with "array_walk" or "array_map", but it doesn't work when the data has array.
So make extended stripslashes function.
<?php
function my_stripslashes($vals) {
if (is_array($vals)) {
foreach ($vals as $key=>$val) {
$vals[$key]=my_stripslashes($val);
}
} else {
$vals = stripslashes($vals);
}
return $vals;
}
$data = addslashes(serialize($_POST));
...
$SQL="insert into DB() values($data)";
...
$SQL="select data from DB";
...
$data = my_stripslashes($data);
...
?>
17-Jul-2001 08:39
BEWARE: if you serialize to store values on a database, and the variables you are serializing already have the " (double-quote) char, you may have a problem. After serializing you will have var delimiters as " and content " (double-quotes) escaped, but your databse may just treat them like the same. You end up with a failed unserialize. You want something like:
a:5:{s:9:"this is a \"quote\"";a:1:{s:(ETC)
And not:
a:5:{s:9:"this is a "quote"";a:1:{s:(ETC)
So just make sure you double escape content quotes ...
It's simple, but i can't explain it any simpler =(
abk at avatartechnology dot com
16-Jul-2001 03:10
BEWARE: if you are serializing a complex object with recursive references, serialize a reference to the object. Otherwise you'll get strange and mysterious results.
Always this: $str = serialize(&$object);
not this: $str = serialize($object);
scott (at) hurring.com
12-Jul-2001 04:44
I have written a perl module that does the same thing as PHP's serialize() and unserialize() commands so that Perl can now serialize and unserialize data in the same format as PHP.
It's quite handy for storing information in databases or files (or anywhere, really) that both PHP and Perl scripts need to read from and write to.
It supports string, double, integer, and array types (no object or reference support).
It's free code, too. :)
URL: http://hurring.com/code/perl/serialize/
sbarnum at mac dot com
24-May-2001 09:53
If you're having trouble with serialized strings, try this function. Pass it the name of an array whose value you want to include in hidden form inputs, a url, or session variable. Works with strings or multidimensional arrays.
<?php
function propogate ($arrayName, $method='form', $arrayData=''){
if($arrayData){
${$arrayName} = $arrayData;
}else{
global ${$arrayName};
}
if ($method == "session"){
session_register(${$arrayName});
return TRUE;
}
@reset(${$arrayName});
while (list($key,$value)=@each(${$arrayName})){
if (is_array($value)){
$subArrayName = $arrayName . "[" . $key . "]";
$html .= propogate ($subArrayName, $method, $value);
}else{
switch ($method){
case "form":
$html .= "<INPUT type='hidden' name='".$arrayName."[".$key."]' value='".htmlspecialchars($value)."'>\n";
break;
case "url":
$html .= "&".$arrayName."[".$key."]=" . urlencode($value);
break;
}
}
}
return $html;
}
?>
gleb at gleb dot org
20-Jan-2001 06:14
About serializing the arrays via hidden fields:
1st page:
$arr1 = array("HELLO");
<input type="hidden" name="arr1" value="<? echo urlencode(serialize($arr1)); ?>">
2nd page:
$arr2 = unserialize(urldecode($arr1));
Important: you have to use urldecode function not stripslashes, simply won't work.
dmb27 at cornell dot edu
22-Oct-2000 06:58
Actually, you don't want to use addslashes() EVER when passing between pages( not in POST when passing in hidden fields, not in GET when appending to a URL). Only use addslashes() with a database, that's the only time it helps you.
However, you still have work to do if you are sending variables to HTML pages. If via Hidden fields in a <FORM> tag, use htmlentities(). This will turn all HTML speical characters into something your browser will interpret as characters, not HTML. When you get to the next page, you don't need to do any decoding.
If you are using GET variables and appending to URL's, use urlencode() on the variable. When you get to the next page, you don't need to do any decoding, your browser did it for you.
nargy at yahoo dot com
11-May-2000 03:46
About serialize/unserialize on objects:
Use this class to unserialize objects :
<?php
class Unserializable
{
function unserialize($str)
{
$ary=unserialize($str);
for(reset($ary);$kv=each($ary);)
{
$key=$kv[key];
if (gettype($this->$key)!="user function")
$this->$key=$kv[value];
}
}
}
?>
MarkRoedel at letu dot edu
22-Feb-2000 12:58
A call to serialize() appears to mess with the array's internal pointer. If you're going to be walking through your array after serializing it, you'll want to make a call to reset() first.
| |