2010-07-31 106 views
4

我已經很好看,並且似乎無法找到此問題的答案。在方法中聲明受保護的變量

基本上我使用_call方法來動態生成get和set方法,但是當聲明一個變量時PHP的默認值是public的。無論如何,從類內部聲明一個變量爲受保護的?

function __call($method, $arguments) { 
    $prefix = strtolower(substr($method, 0, 3)); 
    $property = strtolower(substr($method, 3)); 

    if (empty($prefix) || empty($property)) { 
     return; 
    } 

    if ($prefix == "get" && isset($this->$property)) { 
     return $this->$property; 
    } 

    if ($prefix == "set") { 

     $this->$property = $arguments[0]; 
    } 
} 
+0

出於興趣,您爲什麼使用__call而不是__get和__set? – 2010-07-31 17:08:23

+0

只是似乎更容易,我也從這裏複製它: http://onlamp.com/pub/a/php/2005/06/16/overloading.html – 2010-07-31 17:09:43

回答

6

一種選擇是擁有一個受保護的數組,並從你的魔法設置器中設置該數組中的一個元素。

class MyClass { 
    protected $_myProperties = array(); 

    public function __get($name) { 
     if (isset($this->_myProperties[$name])) { 
      return $this->_myProperties[$name]; 
     } else { 
      return null; 
     } 
    } 

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

    public function __isset($name) { 
     return isset($this->_myProperties[$name]); 
    } 
} 
+0

謝謝,完成了這一步。完美的工作,但保持呼叫方法習慣使用$ class-> getSomething(); – 2010-07-31 17:33:23

2

反正是有作爲保護從類中聲明一個變量?

似乎並不如此。您可以使用Reflectionchange the accessibility of properties,但似乎只能有效地用於公開事先未公開的內容。

您可能希望考慮將自動生成的屬性存儲在具有正確可見性的數組中。

(還有__get__set,但他們可能不適合您的需求。他們會只被調用時,屬性缺失無法訪問。類是能夠觸摸保護的特性會繞過它們。)

+0

是的,我同意你的第二段... ...存儲這些_generated_'屬性'在關聯數組中。關聯數組然後可以是您的類的受保護屬性。爲了使用'__get'或'__set' _我想_你需要這樣做。 – MrWhite 2010-07-31 17:18:35

+0

我不同意。這打破了成員變量的觀點。當類將存儲未知變量(如註冊表類或類似的東西)時,我使用關聯數組。但是當你有一組有限的已知變量時,爲什麼不使用成員變量來設計它們? – ircmaxell 2010-07-31 17:19:44

+0

我只能想象,從這個問題來看,他正在做某種古怪的繼承和/或能見度魔術。除非上面的代碼不完整,否則我不會看到對屬性進行了任何轉換... – Charles 2010-07-31 17:22:08

5

首先,我會強烈建議不要returning如果前綴或屬性變量未設置。它會使調試非常困難。相反,將return;替換爲throw new BadMethodCallException('Method Does Not Exist: '.$method);

其次,是不是破壞了保護變量的點?它允許讀寫所有屬性而不需要任何驗證。如果你打算這樣做,你不妨將它們公諸於衆。

我個人認爲$foo->bar = 'baz';$foo->setBar('baz');更具可讀性。不是因爲它更容易理解,而是因爲第二個是不必要的冗長。

就我個人而言,我會建議做一個__get__set,並添加驗證。保護變量的重點在於信任(以便您可以信任這些設置)。當然,你可以使用反射或分類來改變它們,但我通常假設如果有人走得太遠,如果他們弄亂了一個變量,他們應該有任何意想不到的結果。

而且記住,如果你使用任何類型的魔術方法的,你需要,如果你想你的IDE暗示的方法來添加文檔元素/變量來你...

編輯:

別忘了,如果您聲明__get/__set方法,您可以在子類中覆蓋它們。所以如果孩子聲明瞭新變量,你可以在那裏處理它們,然後調用parent::__get來處理默認變量。所以,不要爲了讓所有的孩子都能擁有一個方法而使用數組。爲你認識的成員做驗證,並讓你的孩子處理他們自己的驗證...

+2

+1不同意$ foo-> setBar('baz');與$ foo-> bar ='baz'相比,是不必要的verbode;因爲getter和setter方法總是允許設置屬性的驗證,而非私有屬性總是可以繞過任何驗證來設置......但是這裏有很多非常有用的信息片段 – 2010-07-31 17:26:35

+0

這只是我可能使用的任何變量的回退方法需要添加到一個類。一般來說,我總是在受保護的變量需要時使用get和set方法。我完全理解調試的困難,只會謹慎地使用這種方法來實現DRY。 – 2010-07-31 17:26:52

+0

嗯,我不時使用'getBar()'語法,但我儘量不去嘗試,除非它真的有意義。我只是不喜歡爲了獲取/設置成員變量而在課堂中使用50個方法的混亂狀態......大多數情況下它不是必需的(但並非總是)... – ircmaxell 2010-07-31 17:34:28