2011-04-25 66 views
7

在Zend的快速入門指南這裏http://framework.zend.com/manual/en/learning.quickstart.create-model.html我們可以看到:Php __get和__set魔術方法 - 爲什麼我們需要這些?

class Application_Model_Guestbook 
{ 
    protected $_comment; 
    protected $_created; 
    protected $_email; 
    protected $_id; 

    public function __set($name, $value); 
    public function __get($name); 


    public function setComment($text); 
    public function getComment(); 
... 

我通常創建我的getter和setter方法沒有任何魔術方法。我在快速指南中看到了這一點,我不明白爲什麼我們需要這個。

任何人都可以幫我嗎?

非常感謝

+7

它減少了打字。而已。 – 2011-04-25 16:17:53

+0

因此,我通常在同一個地方:$ object-> setComment('hello'),我可以改爲:__set($ _ comment,'hello'); ?我相信這不是你所指的,因爲我不會減少打字。再次感謝。 – MEM 2011-04-25 16:20:56

+3

你不直接調用'__get'和'__set'。你只要做到這一點:'$ object - > _ comment ='hello';' – 2011-04-25 16:23:28

回答

10

你(通常情況下)從未__set__get直接調用。如果bar不可見且__get存在,則$foo->bar將自動呼叫$foo->__get('bar')

在你鏈接到教程中,getter和setter獲得設置爲自動調用相應的個人get/set函數。因此$foo->comment = 'bar'將間接呼叫$foo->setComment('bar')。這不是必要的......這只是一個方便。

在其他情況下,__get可以創造什麼看起來像一個只讀變量非常有用。

1

__get__set魔術方法原因存在:

  1. ,這樣你就不必花費時間,所有的屬性創建香草存取方法。

  2. 爲了使您能夠執行財產超載。

如果你有需要特殊處理的屬性,那麼魔法不適合你。然而,如果你的屬性只包含數據而沒有依賴關係,那麼沒有理由不使用魔術方法。

+0

當我們使用神奇方法的時候,以及當我們不使用神奇方法的時候,您能否提供一個與這些情況之間的對比情景。 (一個簡單的)。再次感謝。 – MEM 2011-04-25 16:23:27

+0

老實說,我認爲PHP手冊在解釋魔術方法方面做了很好的工作:http://us2.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members – 2011-04-25 16:27:13

+0

I不同意。 (不幸的是,我發現文檔很混亂,因爲他們有太多的概念沒有解釋,他們認爲只有經過實驗的程序員才能談論魔術方法,或許,但從新手的角度來看,這很難。我的問題有助於我澄清一點 – MEM 2011-04-25 16:38:51

1

進一步的教程,它可以讓你修改__get()__set()方法,所以你會看到他們爲什麼在那裏。

有魔力的處理一樣,可以讓你做一些巧妙的東西一樣,甚至使「只讀」屬性,可以阻止您的getter/setter方法的凌亂負載腹脹類。

9

如果您「製造屬於自己」的獲得者和制定者,您將爲每個屬性制定兩個功能:getPropname()setPropname。通過使用PHP的「神奇方法」setter/getter,你不會爲每個屬性編寫單獨的方法。您可以設置/獲取屬性,就好像它們是公開的。在重載函數中,您可以添加特定於每個屬性的邏輯。例如:

public function __set($name, $value) { 
switch ($name) { 
    case 'comments': 
    // do stuff to set comments 
    break; 
    case 'parent_user': 
    // do stuff to set parent user 
    break; 
} 
} 
public function __get($name) { 
switch ($name) { 
    case 'comments': 
    // do stuff to get comments 
    break; 
    case 'parent_user': 
    // do stuff to get parent user 
    break; 
} 
} 

現在我可以通過使用$obj->comments來設置或獲取評論。

在不使用重載實現上述功能,我將不得不寫4種不同的方法來代替。這實際上更多地是關於代碼組織,無論是在實際文件方面還是在爲項目內的對象創建標準化接口方面。

我個人比較喜歡像你這樣做,併爲每個屬性編寫單獨的方法,我需要一個複雜的getter/setter。對我而言,它的組織更清晰,對象的「簡單」屬性與具有更大複雜性或一對多關係的屬性之間存在明顯的分離。

+0

感謝您的詳細回答 – MEM 2011-04-27 14:38:02

0

當您使用__set並希望覆蓋子類中的setter功能時,您會遇到問題。你必須在整個代碼__set複製,改變只有特定的部分,而不是僅僅簡單地覆蓋一個特定的setter函數 - >冗餘代碼

可以通過調用特定setter__set(感謝cHao來避免此問題爲小費)。

實施例:

class Foo1 { 
    protected $normal; 
    protected $special; 

    public function setSpecial($special) { 
     if ($special == isReallySpecial()) { 
     $this->special = $special; 
     } 
    } 

    public function __set($key, $value) { 
     switch ($key) { 
     case 'normal': 
      $this->normal = $value; 
      break; 
     case 'special': 
      $this->setSpecial($value); 
     } 
    } 
} 

class Foo2 extends Foo1 { 
    public function setSpecial($special) { 
     if ($special == isNotReallySpecial()) { 
     $this->special = $special; 
     } 
    } 
} 
+4

請注意,在這種情況下,'__get'和'__set'方法可能分別調用getter或setter,因爲它們也被指定。在這種情況下,你有'$ obj-> property'和'$ obj - > {get | set}屬性(...)'是一致的,並且這個問題不存在。 – cHao 2012-12-05 20:08:52

相關問題