2014-02-11 27 views
2

我知道有一個類似的線程,但我已經嘗試了他們的建議,它沒有工作。魔術功能__sleep不能返回私有屬性

在php中,當一個對象被序列化時,有一個選項可以在該類中定義魔術函數__sleep,它應該返回一個包含所有要被序列化的對象屬性值的數組。但是在php.net中寫道,如果我們爲一個從另一個類擴展的類的對象定義__sleep方法,那麼我們不能寫入代表父類的私有屬性的數組值。問題是他們爲這種情況提出了一個解決方案,我並沒有真正理解他們想要暗示的內容。

這裏是寫的是:

注:
這是不可能的__sleep()在父類返回私有屬性的名稱。這樣做會導致E_NOTICE級別錯誤。相反,你可以使用Serializable接口。

這裏是鏈接:http://www.php.net/manual/en/language.oop5.magic.php

此外,在this thread他們建議的東西,我想和它不工作,送我:

注意:序列化()「的名字「作爲__sleep()的成員變量返回,但不存在於第43行的C:\ xampp \ htdocs \ questions \ sleep_private_father.php中

以下是腳本:

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

?> 

我也很好奇php.net建議使用serializble接口的方式。

+0

實現[Serializable接口](http://uk3.php.net/manual/en/class.serializable.php)是一個更好的要走的路。 – cmbuckley

+0

你能看看我幾分鐘前發佈的答案嗎?我實現了可序列化,是不是我做到了? – user3021621

+0

'get_class'檢查有點代碼味道IMO;我很想做這樣的事情:http://codepad.org/JuPMm17T – cmbuckley

回答

1

私有操作符表示屬性或函數只能在類中使用,不能擴展。如果你想實現的機制來存儲在子類的屬性,你應該嘗試類似:

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

末方式我用運營商的保護,而不是私人

+0

,但我不明白如何在父類中的私有屬性對象上使用__sleep方法。在php.net中他們建議使用serialize接口,這是什麼意思? – user3021621

0

注意從你的鏈接(PHP .net)意思是:

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. 

如果你會嘗試在__sleep方法數組與私人財產(如果它是父母或孩子類無關緊要)總是你得到通知錯誤。可以避免這種情況,並使用可序列化的接口獲取私有屬性的名稱。

如果你的類實現了可串行化接口,你應該使用__sleep方法,因爲實現此接口的類不再支持__sleep()和__wakeup()方法。 :

Serializable { 
    /* Methods */ 
    abstract public string serialize (void) 
    abstract public void unserialize (string $serialized) 
} 

連載會打電話的時候,你的對象會去序列化狀態(對象 - >字符串)和反序列化時,你的對象會去反序列化(串 - >對象)。您不能在子類中讀取|寫私有屬性父類(當您嘗試從子類中的方法獲取此屬性時)。例如:

class foo implements Serializable{ 
    private $id; 
    public function serialize() { 
     return serialize('hello world'); 
    } 
    public function unserialize($serialized) { 
     $this->id = unserialize($serialized); 
    } 
    public function get_id_from_foo(){ 
     return $this->id; 
    } 
} 

class bar extends foo{ 
    public function get_id_from_bar(){ 
     return $this->id; 
    } 
} 

$bar = new bar(); 
$serializedBar = serialize($bar); 
$unserializedBar = unserialize($serializedBar); 
echo $unserializedBar->get_id_from_bar(); 

//RESULT : Undefined property: bar::$id 

但是,如果您將foo class private $ id更改爲protected $ id,您將獲得'hello world'。

在其他情況下,當您嘗試從母體得到方法extendend私有財產,例如:

class foo implements Serializable{ 
    private $id; 
    public function serialize() { 
     return serialize('hello world'); 
    } 
    public function unserialize($serialized) { 
     $this->id = unserialize($serialized); 
    } 
    public function get_foo_id_from_parent(){ 
     return $this->id; 
    } 
} 

class bar extends foo{ 
    public function set_id(){ 
     $this->id = 'something else'; 
    } 
    public function get_foo_id_from_bar(){ 
     return $this->id; 
    } 
} 

$bar = new bar(); 
$bar->set_id(); 
$serializedBar = serialize($bar); 
$unserializedBar = unserialize($serializedBar); 
echo $unserializedBar->get_foo_id_from_parent(); 
//RESULT 'hello world'; But this property is from parent!! 
0

OK大家給我出出主意,解決我確切的問題,這是越來越結果,如果我能已經在擴展類的睡眠方法中定義了父類的私有屬性。這裏是我的解決方案:

<?php 
class foo implements Serializable 
{ 
    private $id; 
    private $name ; 

    public function serialize() 
    { 
     $array_properties_to_serialize = array('id' => $this->id) ; 

     // this if will indicate if an object from the foo class invoked the method 
     //or an object from the extend class (bar) 

     if (get_class($this) == "foo") 
     { 
      // foo object invoked the method , so we will want to serialize only the $id property 

      return serialize($array_properties_to_serialize); 
     } 

     elseif (get_class($this) == "bar") 
     { 
      // bar object invoked the method so we will want to add to the array of properties 
      //the $last_name property from the bar class, and then serialize it 
      return $array_properties_to_serialize ; 
     } 
    } 

    public function unserialize($serialized) 
    { 
     $array_properties_unserialized = unserialize($serialized); 
     $this->id = $array_properties_unserialized['id'] ; 

     if (get_class($this) == "bar") 
     { 
      // bar object invoked the method so we will send to the overriding method the $array_properties_unserialized 
      // so it could set the properties of the extended object accordingly. 
      return $array_properties_unserialized ; 
     } 
    } 

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

class bar extends foo 
{ 
    private $last_name ; 

    public function serialize() 
    { 
     $array_properties_to_serialize = parent::serialize() ; 
     $array_properties_to_serialize["last_name"] = $this->last_name ; 

     return serialize($array_properties_to_serialize); 
    } 

    public function unserialize($serialized) 
    { 
     $array_properties_unserialized = parent::unserialize($serialized) ; 
     $this->last_name = $array_properties_unserialized['last_name']; ; 
    } 

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


} 

echo "bar object: <br>" ; 
$bar = new bar(12 , "tom" , "smith"); 
var_dump($bar) ; 
$ob_ser = serialize($bar) ; 
$ob_unser = unserialize($ob_ser) ; 
echo "unserialized bar object (didnt include the \$name property): <br>" ; 
var_dump($ob_unser) ; 

$foo = new foo(11 , "frank") ; 
echo "foo object: <br>" ; 
var_dump($foo) ; 
$ob_ser = serialize($foo) ; 
$ob_unser = unserialize($ob_ser) ; 
echo "unserialized foo object (didnt include the \$name property): <br>" ; 
var_dump($ob_unser) ; 

?> 
0

另一種解決方案:

<?php 
    class foo 
    { 
     private $id; 
     private $name ; 

     public function serialize() 
     { 
      $array_properties_to_serialize = array('id' => $this->id) ;   
       return serialize($array_properties_to_serialize); 

     } 

     // will be called only on a foo object because it doesnt implements serializable 
     // when serialize a bar object it will only invoke the serialize method in the bar class 
     public function __sleep() 
     { 
      return array('id') ; 
     } 


     public function getID() 
     { 
      return $this->id ; 

     } 

     public function setId($id) 
     { 
      $this->id = $id ; 
     } 

     public function unserialize($serialized) 
     { 
      $array_properties_unserialized = unserialize($serialized); 
      $this->id = $array_properties_unserialized['id'] ; 


     } 

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

    class bar extends foo implements Serializable 
    { 
     private $last_name ; 

     public function serialize() 
     { 
      $array_properties_to_serialize['id'] = $this->getID() ; 
      $array_properties_to_serialize["last_name"] = $this->last_name ; 

      return serialize($array_properties_to_serialize); 
     } 

     public function unserialize($serialized) 
     { 
      $array_properties_unserialized = unserialize($serialized) ; 
      $this->last_name = $array_properties_unserialized['last_name']; 
      $this->setId($array_properties_unserialized['id']) ; 
     } 

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


    } 

    echo "bar object: <br>" ; 
    $bar = new bar(12 , "tom" , "smith"); 
    var_dump($bar) ; 
    $ob_ser = serialize($bar) ; 
    $ob_unser = unserialize($ob_ser) ; 
    echo "unserialized bar object (didnt include the \$name property): <br>" ; 
    var_dump($ob_unser) ; 

    $foo = new foo(11 , "john") ; 
    echo "foo object: <br>" ; 
    var_dump($foo) ; 
    $ob_ser = serialize($foo) ; 
    $ob_unser = unserialize($ob_ser) ; 
    echo "unserialized foo object (didnt include the \$name property): <br>" ; 
    var_dump($ob_unser) ; 

    ?>