2011-04-25 50 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

相关问题