php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #27785 Change __sleep to always work on copy of object instead of reference
Submitted: 2004-03-30 17:20 UTC Modified: 2014-11-01 22:19 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: brad at info-link dot net Assigned:
Status: Wont fix Package: *General Issues
PHP Version: 5.0.0RC1 OS: Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2004-03-30 17:20 UTC] brad at info-link dot net
Description:
------------
When serializing an object with a __sleep method defined, the original object may be modified by __sleep.  I'd like to see the __sleep method always being called on a copy of the object being serialized and not on the actual object.  In PHP4, this is _mostly_ the case as long as you're not working with references, but in PHP5, the original object is always modified directly.

The example below is a little contrived, but does demonstrate the idea.  Under PHP4, the result is _almost_ as expected, except that the instance of B referenced by $a->b is modified.  If the reference is changed to a plain copy (change the line reading "$a->b = &$b;" to "$a->b = $b;"), then the instance is not modified.

PHP5 gives the output given under actual result, which is probably wrong in either case.

Reproduce code:
---------------
<?php
class B {
  var $b = 'default';
  function __sleep() {
    $this->b = 'serialized';
    return Array('b');
  }
}

class A {
  var $a = "default";
  var $b = null;

  function __sleep() {
    $this->a = "serialized";
    return array_keys(get_object_vars($this));
  }
}


$a = new A();
$b = new B();
$a->b = &$b;
print_r($a);

$s = serialize($a);
print_r($s);
print_r($a);

$na = unserialize($s);
print_r($na);
?>

Expected result:
----------------
a Object
(
    [a] => default
    [b] => b Object
        (
            [b] => default
        )

)
O:1:"a":2:{s:1:"a";s:10:"serialized";s:1:"b";O:1:"b":1:{s:1:"b";s:10:"serialized";}}a Object
(
    [a] => default
    [b] => b Object
        (
            [b] => default
        )

)
a Object
(
    [a] => serialized
    [b] => b Object
        (
            [b] => serialized
        )

)

Actual result:
--------------
A Object
(
    [a] => default
    [b] => B Object
        (
            [b] => default
        )

)
O:1:"A":2:{s:1:"a";s:10:"serialized";s:1:"b";O:1:"B":1:{s:1:"b";s:10:"serialized";}}A Object
(
    [a] => serialized
    [b] => B Object
        (
            [b] => serialized
        )

)
A Object
(
    [a] => serialized
    [b] => B Object
        (
            [b] => serialized
        )

)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-11-01 22:19 UTC] requinix@php.net
-Status: Open +Status: Wont fix -Package: Feature/Change Request +Package: *General Issues
 [2014-11-01 22:19 UTC] requinix@php.net
__sleep/wakeup provide only very simple functionality. PHP 5.1.0 introduced the Serializable interface which gives much more control, allowing you to provide exactly the data you want to serialize without having to modify the object.
http://php.net/manual/en/class.serializable.php

  public function serialize() {
    $vars = get_object_vars($this);
    unset($vars["a"]); // don't serialize this property
    return serialize($vars);
  }
  public function unserialize($string) {
    $vars = unserialize($string);
    // no $vars["a"] means $this->a will keep its current (ie, default) value
    foreach ($vars as $key => $value) $this->$key = $value;
  }
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 12:01:27 2024 UTC