I have an object tree like the following, which I need to serialize and store on the filesystem. I need the full hierarchy with all class properties and later I will unseria
This is how I would recommend serializing objects:
class Color implements \Serializable
{
private $Name;
private $Type;
public function __construct(string $Name, int $Type)
{
$this->Name = $Name;
$this->Type = $Type;
}
public function serialize()
{
$Props['Name'] = $this->Name;
$Props['Type'] = $this->Type;
return serialize($Props);
}
public function unserialize($Data)
{
list($this->Name, $this->Type) = unserialize($Data);
}
}
class Blue extends Color
{
private $Intensity;
public function __construct()
{
parent::__construct('Blue', 10);
$this->Intensity = 90;
}
public function serialize()
{
$Props['parent'] = parent::serialize();
$Props['Intensity'] = $this->Intensity;
return serialize($Props);
}
public function unserialize($Data)
{
$Obj = unserialize($Data);
parent::unserialize($Obj['parent']);
$this->Intensity = $Obj['Intensity'];
}
}
Whichever object you pass in to the serialize() function is the object you will get back (as a string) to unserialize(). If you go your route, then you can implement the serialize()/unserialize() functions inside a trait and get_object_vars() will work properly for private variables.
I have implemented serialize() and unserialize() in every affected class like this:
public function serialize() {
$res = array();
$reflect = new \ReflectionClass(__CLASS__);
$propList = $reflect->getProperties();
foreach($propList as $prop) {
if ($prop->class != __CLASS__) {
continue; // visible properties of base clases
}
$name = $prop->name;
$res[$name . ":" . __CLASS__] = serialize($this->$name);
}
if (method_exists(get_parent_class(__CLASS__), "serialize")) {
$base = unserialize(parent::serialize());
$res = array_merge($res, $base);
}
return serialize($res);
}
public function unserialize($data) {
$values = unserialize($data);
foreach ($values as $key => $value) {
// key contains propertyName:className
$prop = explode(":", $key);
if ($prop[1] != __CLASS__) {
continue;
}
$this->$prop[0] = unserialize($value);
}
// call base class
if (method_exists(get_parent_class(__CLASS__), "unserialize")) {
parent::unserialize($data);
}
}
Maybe there is a solution to add this functionality to a base class to prevent code copies. It should work with simple properties, arrays and objects also for large object trees with multiple levels of parent classes.