在Zend快速入门指南这里http://framework.zend.com/manual/en/learning.quickstart.create-model.html我们可以看到:
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而不使用任何魔法方法。我在快速指南上看到了这个,我不明白为什么我们需要这个。
有谁能帮我吗?Thanks to lot
您(通常)从不直接调用__set
或__get
。如果bar
不可见且__get
存在,$foo->bar
将自动调用$foo->__get('bar')
。
在你所链接到的教程中,getter和setter被设置为自动调用适当的单个get/set函数。所以$foo->comment = 'bar'
会间接调用$foo->setComment('bar')
。这没有必要……这只是为了方便。
在其他情况下,__get
可以用来创建一个只读变量。
如果您"自制" getter和setter,您将为每个属性制作两个函数: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的每个属性编写单独的方法。对我来说,它的组织更清晰,对象的"简单"属性和那些更复杂或一对多关系的属性之间有明确的分离。
__get
和__set
魔术方法存在两个原因:
-
这样你就不必花时间为你所有的属性创建普通的访问方法。
-
允许你实现属性重载
如果您有需要特殊处理的属性,那么魔法方法不适合您。然而,如果你的属性只是包含数据,没有依赖关系,那么没有理由不使用魔法方法。
在本教程中,您将进一步修改__get()
和__set()
方法,以便您了解它们存在的原因。
拥有这样的神奇处理可以让你做一些整洁的事情,甚至可以创建"只读"属性,并且可以防止你用杂乱的getter/setter加载来膨胀你的类。
当您使用__set
并希望在子类中覆盖setter功能时,您将遇到问题。您必须复制__set
中的整个代码并仅更改特定部分,而不是简单地覆盖一个特定的setter函数->冗余代码
这个问题可以通过在__set
中调用特定的setter
来避免(感谢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;
}
}
}