2013-08-27 58 views
0

考慮下面的例子:這是一個PHP的OO錯誤?

<?php 

class Model 
{ 

    private $data = []; 

    public function __set($property, $value) 
    { 
     $this->data[$property] = $value; 
    } 

    public function __get($property) 
    { 
     if(isset($this->data[$property])) 
     { 
      return $this->data[$property]; 
     } 
     throw new Exception("Error trying to access undefined data"); 
    } 

    public static function all() 
    { 
     // returns all models 
    } 

    public function save() 
    { 
     // save something to database 
    } 
} 

這個類:

class Person extends Model 
{ 
    protected $name; 

    public static function migrateNamesToUppercase() 
    { 
     foreach(self::all() as $person) 
     { 
      $person->name = strtoupper($person->name); 
      $person->save(); 
     } 
    } 

} 
  • 內部靜態方法 「人:: migrateNamesToUppercase」 $person->name爲空。

  • 外部靜態方法「Person :: migrateNamesToUppercase」(new Person())->name將引發預期的異常。

當類實例住同一類PHP的靜態方法裏面就假定它能夠訪問受保護的財產,既不__get__set執行!可悲的是,私人財產也會發生同樣的情況。

我的問題是:在兩種情況下,實例的行爲不應該是相同的嗎?這是一個已知的bug還是僅僅是一個失敗的PHP OO實現?

  • 我GOOGLE了一下,沒有發現任何
+0

您正在運行PHP 5.4或5.5,它們是不同的版本 –

+0

它發生在兩個版本中。我不確定5.3 – marcio

+0

沒有任何面向所有靜態方法的對象... – rdlowrey

回答

4

__get()被用於從人跡罕至的屬性讀取數據。

See the PHP manual for details

它的工作定義。可以從對象訪問$name,因此它不使用該方法。如果$name是私有的,並且在父類中定義,則它將不可訪問,因此將使用該方法。

+0

我的觀點是它不應該。該實例具有受保護的屬性,並且在該靜態方法內,該屬性的行爲與公共一樣。對我來說看起來並不合適,所以我認爲這可能是一個錯誤或實施失敗。 – marcio

+0

這是正確的。您可以在嘗試訪問內部屬性時調用'$ this - > __ get('varname')',並且可能需要額外的處理。 –

+2

@marcioAlmada從根本上說,當你將一個靜態方法放在另一個類中時,你正在做出一個設計決定。我認爲這是完全合理的行爲,因爲'__get()'[你無論如何都在用滑稽的愚蠢的方式]的定義] –