Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

magic function __sleep cannot return private properties

I know that there is a similar thread but I have tried what they suggested and it didn't work.

in php when an object is serialized there is an option do define in that class the magic function __sleep which is supposed to return an array with the values of all the object properties that would be serialized. But in php.net it is written that if we define the __sleep method for a object of a class that extends from another class then we cant write in the array values that represent private properties from the parent class. the thing is that they suggested a solution for this kind of situation, and I didn't really understood what they were trying to insinuate.

Here is what is written:

Note:
It is not possible for __sleep() to return names of private properties in parent classes. Doing this will result in an E_NOTICE level error. Instead you may use the Serializable interface.

Here is the link: http://www.php.net/manual/en/language.oop5.magic.php

Also, in this thread they suggested something that I tried and it didn't work and sent me:

Notice: serialize(): "name" returned as member variable from __sleep() but does not exist in C:\xampp\htdocs\questions\sleep_private_father.php on line 43

Here is the script:

<?php

class a
{
    private $name ;
    private $age ;

    function __construct($name, $age)
    {
        $this->name = $name ;
        $this->age = $age ;
    }

    function __sleep()
    {
        $vec = array("name") ;
        return $vec ;
    }
}

class b extends a
{
    private $last_name ;

    function __construct($name, $age ,$last_name)
    {
        parent::__construct($name, $age) ;
        $this->last_name = $last_name ;
    }

    function __sleep()
    {
        $array = parent::__sleep() ;

        array_push( $array, 'last_name' );
        return $array ;
    }

}

$ob = new b("michal" , 26 , "smith") ;
var_dump($ob) ;
$ob_ser = serialize($ob) ;
var_dump(unserialize($ob_ser)) ;

?>

I'm also curious of the way that php.net suggested to use the serializble interface.

like image 501
user3021621 Avatar asked Jun 17 '26 21:06

user3021621


2 Answers

Private operator mean that the attribute or function can be used only in class and cant be extends. If you want implement mechanism to store attribute in child class you should try something like:

  class foo{
     protected $test = 'a';
     public function __sleep() {
           return array('test');
     }
  }
  class bar extends foo{

     public function getTest(){
          return $this->test;
  }

}   

 $bar = new bar();
 $serialized = serialize($bar);
 $object = unserialize($serialized);
 echo $object->getTest();

OR

 class foo{
     protected $test = 'a';
 }
 class bar extends foo{

     public function __sleep() {
        return array('test');
    }

    public function getTest(){
        return $this->test;
    }

 }

 $bar = new bar();
 $serialized = serialize($bar);
 $object = unserialize($serialized);
 echo $object->getTest();

Last way i used operator protected instead private

like image 131
ZiupeX Avatar answered Jun 20 '26 11:06

ZiupeX


You can do small hack if you name parent property like this "\0". parent::class. "\0parentProperty"

<?php
namespace bed {
class A {
    private $id=5;
    protected $b;
    public $c;
    public function __sleep()
    {
        return ['id'];
    }
}

class B extends A{
    public function __sleep(){
        return  parent::__sleep();
    }
}

class D extends A{
    public function __sleep(){
        return ["\0bed\A\0id"];
    }
}

class CoolD extends A {
    private $d;
    protected $e;
    public $f;

    public function __sleep(){
        $allProperties = [];
        $reflection  = new \ReflectionClass($this);
        do{
            foreach ($reflection->getProperties() as $prop) {
                $allProperties[($prop->isPrivate()
                    ? "\0" . $prop->getDeclaringClass()->getName() . "\0" . $prop->getName()
                    : $prop->getName())] = true;
            }
        }while($reflection = $reflection->getParentClass());
        return array_keys($allProperties);
    }
}

class C extends A{
}

// var_dump(serialize(new C)); - not working
// var_dump(serialize(new B)); - not working
var_dump(serialize(new D));
var_dump(serialize(new CoolD));
}

https://3v4l.org/ZpPhR

like image 30
Adam Mátl Avatar answered Jun 20 '26 11:06

Adam Mátl