2012-11-14 65 views
2

我通過利用__get魔術方法來定義在訪問不存在的屬性時會發生什麼情況。__get魔術方法 - 如何拋出並捕獲屬性重載的錯誤?

因此,如果$property->bla不存在,我會得到null

return (isset($this->$name)) ? $this->$name : null; 

但我想拋出,趕上錯誤$property->bla->bla當我知道$property->bla不存在。

return (isset($this->$name)) ? $this->$name : null;我會得到下面這個錯誤,

<b>Notice</b>: Trying to get property of non-object in... 

所以我在課堂上使用throw and catch錯誤,

類屬性 {

public function __get($name) 
{ 
    //return (isset($this->$name)) ? $this->$name : null; 

    try { 
     if (!isset($this->$name)) { 
      throw new Exception("Property $name is not defined"); 
     } 
     return $this->$name; 
     } 
     catch (Exception $e) { 

     return $e->getMessage(); 
     } 
} 

}

但結果不是我所知道的螞蟻因爲它throw錯誤消息("Property $name is not defined")而不是null$property->bla

我該如何才能讓它出錯只有對於$property->bla->bla$property->bla->bla->bla等等?

回答

1

其實當你打電話給$property->foo->bar$property類有魔法__get方法時,你只能驗證foo屬性並且只爲它拋出錯誤。

但是,如果您的foo也是同一類的實例(或具有相同魔術__get方法的類似實例),那麼您還可以驗證bar屬性並拋出下一個錯誤。

例如:

class magicLeaf { 
    protected $data; 
    public function __construct($hashTree) { 
     $this->data = $hashTree; 
    } 
    // Notice that we returning another instance of the same class with subtree 
    public function __get($k) { 
     if (array_key_exists($k, $this->data)) { 
      throw new Exception ("Property $name is not defined"); 
     } 
     if (is_array($this->data[$k])) { // lazy convert arrays to magicLeaf classes 
      $this->data[$k] = new self($this->data[$k]); 
     } 
     return $this->data[$k]; 
    } 
} 

而現在使用它只是例子:

$property = new magicLeaf(array(
    'foo' => 'root property', 
    'bar' => array(
     'yo' => 'Hi!', 
     'baz' => array(
      // dummy 
     ), 
    ), 
)); 
$property->foo; // should contain 'root property' string 
$property->bar->yo; // "Hi!" 
$property->bar->baz->wut; // should throw an Exception with "Property wut is not defined" 

所以,現在你可以看到如何使得它幾乎就像你想要的。

現在只需修改一點點你__construct和魔法__get方法和添加新的參數去知道我們在每個級別:

... 
    private $crumbs; 
    public function __construct($hashTree, $crumbs = array()) { 
     $this->data = $hashTree; 
     $this->crumbs = $crumbs; 
    } 
    public function __get($k) { 
     if (array_key_exists($k, $this->data)) { 
      $crumbs = join('->', $this->crumbs); 
      throw new Exception ("Property {$crumbs}->{$name} is not defined"); 
     } 
     if (is_array($this->data[$k])) { // lazy convert arrays to magicLeaf classes 
      $this->data[$k] = new self($this->data[$k], $this->crumbs + array($k)); 
     } 
     return $this->data[$k]; 
    } 
... 

我認爲它應該像你的作品想。

2

你不能。

__get()函數的範圍內,您只知道$property->blah。你不知道後面會發生什麼,因爲那是語言的功能。

注意評價上$foo = $property->blah->blah2->blah3順序:

  1. $temp1 = $property->blah;
  2. $temp1 = $temp1->blah2;
  3. $foo = $temp1->blah3;

當然,$temp1是虛構的,但是這基本上是執行會發生什麼該聲明。您的__get()調用只知道該列表中的第一個呼叫,僅此而已。你可以做的是處理主叫側的錯誤,用property_exists()或檢查null

$temp = $property->blah; 
if($temp === null || !property_exists($temp, 'blah2')) { 
    throw new Exception("Bad things!"); 
} 

注意,如果對象$temp恢復還依賴於__get()property_exists()會失敗,但說不清楚OP。

相關問題