2017-08-02 81 views
1

我有一個像下面這樣的對象樹,我需要序列化並存儲在文件系統上。我需要具有所有類屬性的完整層次結構,稍後我將反序列化並還原類層次結構。PHP序列化對象樹

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

我在每一個受影響的類實現序列化()和反序列化()是這樣的:

 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); 
      } 
    } 

也許有這個功能添加到一個基類,以防止代碼拷貝的解決方案。它應該適用於具有多級父類的大型對象樹的簡單屬性,數組和對象。

0

這是我會怎麼推薦序列化對象:

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']; 
    } 
} 

無論對象,你在傳遞給序列化()函數的對象,你會回來(字符串)反序列化()。如果你走你的路線,那麼你可以在一個trait中實現serialize()/ unserialize()函數,而get_object_vars()對於私有變量將正常工作。