我有一个像下面这样的对象树,我需要在文件系统上进行序列化和存储。我需要具有所有类属性的完整层次结构,稍后我将反序列化并恢复类层次结构。
class X implements \Serializable {
private $x1;
public function serialize() {
return serialize(get_class_vars(get_class($this)));
}
public function unserialize($data) {
$values = unserialize($data);
foreach ($values as $key => $value) {
$this->$key = $value;
}
}
}
class A implements \Serializable {
private $a1;
private $a2;
// type of a3 is class X!
protected $a3;
public function serialize() {
return serialize(get_class_vars(get_class($this)));
}
public function unserialize($data) {
$values = unserialize($data);
foreach ($values as $key => $value) {
$this->$key = $value;
}
}
}
class B extends A implements \Serializable {
private $b1;
private $b2;
public function serialize() {
// $base = parent::serialize();
return serialize(get_class_vars(get_class($this)));
}
public function unserialize($data) {
$values = unserialize($data);
foreach ($values as $key => $value) {
$this->$key = $value;
}
}
}
class C extends A implements \Serializable {
private $c1;
private $c2;
public function serialize() {
// $base = parent::serialize();
return serialize(get_class_vars(get_class($this)));
}
public function unserialize($data) {
$values = unserialize($data);
foreach ($values as $key => $value) {
$this->$key = $value;
}
}
}
子类可以自行序列化,但对于我不知道的基类,如何组合序列化数据。此外,我从文件系统获取序列化数据,但我不知道,我会得到哪个子类。 PHP的unserialize()是否创建了正确的类实例?它还应该初始化基类A.
我该如何解决?
也许我可以使用var_dump()输出,但是如何将它存储到变量中呢?
答案 0 :(得分:1)
这就是我建议序列化对象的方法:
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'];
}
}
您传递给serialize()函数的对象是您将返回(作为字符串)取消序列化()的对象。如果你走你的路线,那么你可以在trait中实现serialize()/ unserialize()函数,get_object_vars()将适用于私有变量。
答案 1 :(得分:0)
我已在每个受影响的类中实现了serialize()和unserialize(),如下所示:
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);
}
}
也许有一种解决方案可以将此功能添加到基类以防止代码副本。它应该适用于具有多级父类的大对象树的简单属性,数组和对象。