search for in the  
<parentThe magic functions __sleep and __wakeup>
Last updated: Thu, 19 May 2005

Serializing objects - objects in sessions

Note: In PHP 3, objects will lose their class association throughout the process of serialization and unserialization. The resulting variable is of type object, but has no class and no methods, thus it is pretty useless (it has become just like an array with a funny syntax).

Caution

The following information is valid for PHP 4 only.

serialize() returns a string containing a byte-stream representation of any value that can be stored in PHP. unserialize() can use this string to recreate the original variable values. Using serialize to save an object will save all variables in an object. The functions in an object will not be saved, only the name of the class.

In order to be able to unserialize() an object, the class of that object needs to be defined. That is, if you have an object $a of class A on page1.php and serialize this, you'll get a string that refers to class A and contains all values of variabled contained in $a. If you want to be able to unserialize this on page2.php, recreating $a of class A, the definition of class A must be present in page2.php. This can be done for example by storing the class definition of class A in an include file and including this file in both page1.php and page2.php.

<?php
// classa.inc:
 
 
class A {
     var
$one = 1;
  
     function
show_one() {
         echo
$this->one;
     }
  }
 
// page1.php:

 
include("classa.inc");
 
 
$a = new A;
 
$s = serialize($a);
 
// store $s somewhere where page2.php can find it.
 
$fp = fopen("store", "w");
 
fwrite($fp, $s);
 
fclose($fp);

// page2.php:
 
  // this is needed for the unserialize to work properly.
 
include("classa.inc");

 
$s = implode("", @file("store"));
 
$a = unserialize($s);

 
// now use the function show_one() of the $a object. 
 
$a->show_one();
?>

If you are using sessions and use session_register() to register objects, these objects are serialized automatically at the end of each PHP page, and are unserialized automatically on each of the following pages. This basically means that these objects can show up on any of your pages once they become part of your session.

It is strongly recommended that you include the class definitions of all such registered objects on all of your pages, even if you do not actually use these classes on all of your pages. If you don't and an object is being unserialized without its class definition being present, it will lose its class association and become an object of class stdClass without any functions available at all, that is, it will become quite useless.

So if in the example above $a became part of a session by running session_register("a"), you should include the file classa.inc on all of your pages, not only page1.php and page2.php.



User Contributed Notes
Serializing objects - objects in sessions
kendlj at NOSPAM dot web dot de
21-Apr-2005 07:51
Was wondering, if References are also lost after serializing and deserializing in php5.

Wrote a testfile and my result is:
All references are restored corretly. Even if the classes where recursively referenced.

Here is the code of the file:

<?
//check refereneces

class A
{
   public
$a_var;
  
/**
   * @var B
   */
  
public $parent;
  
   public function
__construct($parent)
   {
      
$this->parent=$parent;
   }
}

class
B
{
  
/**
   * @var A
   */
  
public $Ref_auf_A;
  
/**
   * @var A
   */
  
public $aObj;
  
   public
$name="";
  
   public function
__construct($InhaltA)
   {
      
$this->aObj=new A($this);
      
$this->aObj->a_var=$InhaltA;
      
      
$this->Ref_auf_A=$this->aObj;
   }
}

$B_obj = new B("Inhalt von A");
$B_obj->name="My is <defaultName>";

echo
"Object B before serializing:<pre>";
print_r($B_obj);
echo
"</pre><br><br>";

$serB=serialize($B_obj);
echo
"Object B serialized: ".$serB."<br><br>";

$B_obj = unserialize($serB);
echo
"Object B deserializedt:<pre>";
print_r($B_obj);
echo
"</pre><br><br>";

$B_obj->Ref_auf_A->a_var="Test";
echo
"Object A reference content changed, should have changed everywhere:<pre>";
print_r($B_obj);
echo
"</pre><br><br>";

//Change name of object where A parent references to.
$B_obj->Ref_auf_A->parent->name="My name changed";

echo
$B_obj->name;

?>
fdreger at amiga dot pl
19-Mar-2005 07:43
It seems that serializing an object dereferences all its attributes that were references - even if the object they referenced was contained within the serialized one.
Consider this example:

<?
class foo {
  var
$a=new array();
}

$example=new foo;
$obj=new whatever();
$example->a[]=&$obj;
$example->a[]=$obj;

//now $example contains a list with
//both: an object and a reference to that object

//let us serialize and immediately unserialize $example:

$string=serialize(example);
$example=unserialize(string);

//now the situation is completely different!
//$example contains just two identical objects,
//the reference is lost
?>
evan dot php dot net at timewarp dot org
03-Jun-2004 05:45
A special gotcha for unserializing stored objects.  If you alter the class (adding new methods), they will appear and be available when the object is unserialized.  If, however, you alter the parent class that the class extends, the methods are *not* available, and any renamed ones silently vanish (the method disappears and does not reappear under the new name).

A way to get around this is to create a new dummy method in the child class and rename it each time you alter the parent class.  This is very much a Bad Solution when you have to deal with a base class that is extended by dozens of other classes.  Especially when you have a database full of serialized objects, each of which is a child of the base class.  There appears to be no runtime fix.

Applies to PHP 4.  Not sure about 5.
markg at byu dot edu
05-May-2004 06:32
When working with a installation where Register Globals if off.  You must remeber to use $_SESSION['objectName'] to  store objects that will be used on multiple pages.

To re-use a saved object, you must define your object (i.e. include it's class file) before you call session_start(), or the object becomes unusable.
arthurp at nospam free dot fr
21-Nov-2003 03:00
Good news when serializing a class and then reading it back into the similar or modified class.
PHP behaves very well when a class was serialized and then it is unserialized to initialize similar class or when the class was modified meanwhile.

Try this sample:
First version of the class A contains members $one and $three. An instance of this class is stored into the file.

The second version of the class A contains members $one as in prevoius but it also contains $two and and it doesn't contain $three member. The file is read back.
Resulting class is still working !

<?php
/////////////////////////////
// classa.inc:
class A
{
   var
$one = 1;
   var
$three = 3;
   function
show_one(){ echo $this->one."<br>";}
}

/////////////////////////////
// classa_modified.inc:
class A
{
   var
$two = 2;
   var
$one = 1;

   function
show_one(){ echo $this->one."<br>"; }
   function
show_two(){ echo $this->two."<br>"; }
}

/////////////////////////////
// teststore
include("classa.inc");

$a = new A;
$s = serialize($a);
// store $s somewhere where page2.php can find it.
$fp = fopen("savedclass.tmp", "w");
fputs($fp, $s);
fclose($fp);

$a->show_one();
var_dump($a);

/////////////////////////////
// testreadmodified.php:
include("classa_modified.inc");

$s = implode("", @file("savedclass.tmp"));
$a = unserialize($s);

// now use the function show_one() of the $a object. 
$a->show_one();
$a->show_two();
var_dump($a);
?>

Resulting Output:
1
2
object(a)(3) { ["two"]=> int(2) ["one"]=> int(1) ["three"]=> int(3) } ?>

Note:
- $one member is unserialized normally
- $two member exist after unserialisation and it's well initialised with value 2
- show_two() function is working after unserialization
- $thee member exist was loaded too even if it isn't declared in modified version of the class !
okoro22 at yahoo dot com
04-Mar-2003 07:21
I had a problem using session_register() to globally store a class that I was working with. I hope my solution will help beginners understand this concept of sessions in PHP

When you use session_register() to store any object, yes you don't need to call session_start() unless you want to. However in other pages where you want to use that object, you must call session_start() after you have included the class definition of the file. Failure to do this will unserlize your object without its functions and it will be pretty useless.

Hope it helps someone.

Cheers.
dan at binaryfrost dot net
15-Nov-2002 12:10
Serialization is very useful for the storing of objects in databases.
The following example stores an obbect in a mySQL db:

# Seperate Class.
include 'thisObjectClass.php';

# Create instance of a class.
$object = new thisObjectClass;

# Create link to the database
$link = mysql_connect('host', 'user', 'password');
mysql_select_db('dbname', $link);

# Formulate query and submit.
$sql_query = mysql_query("INSERT INTO objecttable(object) VALUES (serialize($object)") or print (mysql_error());

# Retrieve blob object.
$sql_query = mysql_query("SELECT object FROM objecttable WHERE 1) or print (mysql_error());
$row = mysql_fetch_row($sql_query);

# This should show string / text data.
print $row[0];

# This should show 'object'.
print unserialize($row[0])."<br>";

# Close db link.
mysql_close($link);
michael at nospam dot dynamine dot net
14-Nov-2002 11:07
Don't forget to lock your storage file using flock() before opening the file you wish to use to store your serialized object(s)!    PHP will make no attempt to prevent two threads or processes from writing to your file at the same time and you can easily end up with a corrupted data store unless you serialize access to your storage.  (Note that using NFS for your storage may not be lock-safe.)
evan at unixpimps dot org
25-Aug-2002 01:26
A quick note about objects containing another object as a variable. Say you have something like this:

class A {
var $A_Var;
}

class B {
var $A
var $B_Var;
function B() {
$this->A = new A();
}
}

$B = new B();
$B->A->A_Var = "A_Var value";

---

When you try to serialize() an instance of B() $B->A->A_Var doesn't seem to keep it's value.

After much fighting with this the solution I found was to append to my __sleep and __wakeup functions and serialize $this->A in __sleep and then unserialize it in __wakeup.

class A {
var $A_Var;
}

class B {
var $A
var $A_serialized;
var $B_Var;
function B() {
$this->A = new A();
}

function __sleep() {
$this->A_serialized = serialize($this->A);
return array('A_serialized', 'B_Var');
}
function __wakeup() {
$this->A = unserialize($this->A_serialized);
}
}
felizk at hotmail dot com
08-Jul-2002 02:31
Got around the session_auto_start problem by using:

session_write_close();
class defination
session_start();

works for me
I hate spam
08-Jul-2002 02:57
The deserialize callback function is pretty useless if you name your classes and files using title case (ie ClassName.php), because PHP changes all classnames to lower case!!!
ndp9 at yahoo dot com
26-May-2002 07:13
In case this isn't clear:
In 4.2 and below: session.auto_start and session objects are mutually exclusive.
hhuggins at fedex dot com
17-Apr-2002 03:52
The problem with objects during session management arise because the object definition must exist before starting the session.  i.e. if you have object x and you want to use it in a session, you have to perform the following.

<?

class x
{
...
definition here
}

// php now knows what x is... start the session

session_start();
session_register("x_as_variable");

?>

if object x is defined in another file, make sure that the file is included or required BEFORE you start the session.

<?
require("x.inc");

session_start();
session_register("x_as_variable");
?>

This stops the INCOMPLETE_OBJECT response eliminating the need to create an array representation for an object.
ggiulb at netscape dot net
17-Mar-2002 09:00
PHP.INI FILE AND SESSION.AUTO_START

Set

session.auto_start = 0

in php.ini file if you want that all works well during serialization/unserialization.

If session.auto_start is set to 1 all class definition is loaded after unserialization process, infact you obtain a messagge error  like this "The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition className of the object you are trying to operate on was loaded _before_ the session was started in scriptFile on line n"
grant_mjtr at hotmail dot com
20-Feb-2002 03:15
A quick note about automatic serialisation in sessions.

If you have an object
$myCart = new ShoppingCart(); 

and this object contains variables which are objects
function ShoppingCart()
{
   $mySingleItem = new BasketItem();
}
this will work fine and you can access the contained object $mySingleItem and its methods etc ONLY WHILE YOU ARE ON THE PAGE WHERE YOU CREATED IT.

if you are using sessions and register the cart
session_register('myCart')

the ShoppingCart object is serialised and unserialised on the next page ok but the inner BasketItem object is just garbled.

The only solution I have found is to use an array in the ShoppingCart instead of an object.  What a pain!
william at scriptingbiz dot com
22-Sep-2001 07:03
When storing an object that was generated with:

 $row = mysql_fetch_object($result)

there is no apearent way to define the class of that object in the next page, without querying the database, and fetching a row as an object.  This needs to be done so any such objects can be restored (deserialized) from a PHP4 Session. 

It needs to be done before session_start() or session_register().

<parentThe magic functions __sleep and __wakeup>
 Last updated: Thu, 19 May 2005
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: The Server Pages
Last updated: Thu May 19 17:35:34 2005 CDT