php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #35579 Serialize / Unserialize Behavior with Objects including References
Submitted: 2005-12-07 09:20 UTC Modified: 2006-09-06 19:48 UTC
From: al dot the dot x at gmail dot com Assigned: colder (profile)
Status: Closed Package: Documentation problem
PHP Version: Irrelevant OS: ANY
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: al dot the dot x at gmail dot com
New email:
PHP Version: OS:

 

 [2005-12-07 09:20 UTC] al dot the dot x at gmail dot com
Description:
------------
As discussed in several bug reports and in the 
additional comments in the PHP Documentation site 
(eventually, with some reading / searching), the 
functions serialize() and unserialize() do not restore 
references to other objects in PHP 4. As that this 
behavior is unexpected _and_ intrinsic to the use of 
session data in PHP, please consider including a caveat 
or clarification in the documentation XML for the 
affected functions, the "Classes and Objects" section,  
and the "Session-Handling Functions" section.

Certainly, there's a workaround with __sleep() and 
__wakeup(), but this really needs to be addressed in the 
primary documentation in all these places, since the 
thread regarding that behavior is now buried among 
others and only appears on the description of 
serialize().

I also understand that this has been fixed as of PHP 5, 
but that's not a very helpful explanation, Most hosting 
providers currently run PHP 4.3.x or 4.4.x and place low 
priority on upgrading until the next major Apache 
version is released (maybe not even then, the slackers).

Reproduce code:
---------------
// Consider:

class dataObject {
  var $data = NULL;
  var $pointer = NULL;

  function dataObject ($newData = false) {
    if ($newData !== false) $this->data = $newData;
  } // END constructor

  function setPointer (&$newPtr) {
    return ($this->pointer =& $newPtr);
  } // END setPointer

} // END class dataObject

$A = new base('This is A');
$B = new base('This is B');
$A->setPointer(&$B);
$C = serialize($A);

// Now check the original for reference...

$B->data = "Still B, but different";
echo $A->pointer->data; // Funky syntax, I know...

// Output as expected: "Still B, but different"
// But do the same on the serialized version...

unset($A);
$A = unserialize($C);
$B->data = "Where's B now?";
echo $A->pointer->data;

// Output is old "This is B"... Not cool.
// Reference is not preserved.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-12-14 13:16 UTC] sniper@php.net
And write with big letters "references are NOT pointers!" :)
 [2005-12-15 02:29 UTC] al dot the dot x at gmail dot com
Also, as I've discovered in further testing, even 
internal references are not preserved when serialize() 
and unserialize() are employed. For instance (mind the 
pun, it's tricky): 

Sample Code:
============

class A {
  var $value = 0;

  function A ( $newValue = 0 ) {
    $this->value = $newValue;
  } // END constructor
} // END class A

class B {
  var pointers = array(); 
  vae aliases = array();
  // Excuse the misnomers, please...

  function B ( $newPointer = false ) {
    if (false !== $newPointer) 
      $this->ponters[] =& $newPointer;
    foreach ($pointers as $index => $value)
      $this->aliases[$index] =& $pointers[$index];
  } // END constructor
} // END class B

$newA = new A('I'm a new A'); 
$newB = new B(&$newA);
$oldB = unserialize(serialize($newB));
$newA->value = "Now I'm an old A";

// Forgive the PHP5-style syntax below...

echo $newA->value; 
// As expected, Output: Now I'm an old A

echo $newB->pointer[0]->value;
// As expected, Output same...

echo $oldB->pointers[0]->value;
// Somewhat expected, but not desired...
// Output: I'm an old A

$oldB->pointers[0]->value = "Also an old A";
echo $oldB->pointers[0]->value;
echo $oldB->aliased[0]->value;
// Nothing as expected or desired...
// Output 1: Also an old A
// Output 2: I'm an old A
// Internal references aren't even preserved... Boo.
 [2005-12-15 16:28 UTC] colder@php.net
I fail to see the specific link with objects, nor the dilemnia, because serialize/unserialize can't keep references at all:

$a = 'first';
$b = &$a; // create a reference
$c = serialize($b);
unset($b); // kill the reference
$b = unserialize($c); // won't restore it, unserialize() doesn't return a reference.
$a = 'second';
echo $b;
-> 'first'
 [2005-12-15 16:43 UTC] colder@php.net
Well, as a second though, I would agree that the manual isn't clear enough. 

"References inside the array/object you are serialize()ing will also be stored."

$a = 'first';

$b = array(&$a);

$c = serialize($b);
unset($b);

$b = unserialize($c);
$a = 'second';

echo $b[0]; // -> first, which is not the behavior somebody would expect

 [2006-09-06 19:48 UTC] colder@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.


 [2020-02-07 06:11 UTC] phpdocbot@php.net
Automatic comment on behalf of colder
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=b1bf8135a624e1561480de3b6ecd236f2c75094a
Log: Fix #35579 (Ambiguity about how serialize keeps references)
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Tue Jul 08 20:01:34 2025 UTC