在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。我在快速指南上看过这个,我不明白为什么我们需要这个。
任何人都可以帮助我吗?
非常感谢
答案 0 :(得分:10)
您(通常)不会直接致电__set
或__get
。如果$foo->bar
不可见且$foo->__get('bar')
存在,bar
会自动致电__get
。
在您链接到的教程中,getter和setter设置为自动调用相应的单个get / set函数。因此$foo->comment = 'bar'
会间接致电$foo->setComment('bar')
。这不是必要的......这只是一种便利。
在其他情况下,__get
可用于创建看似只读变量的内容。
答案 1 :(得分:9)
如果你“自己制作”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。对我而言,它组织得更清晰,对象的“简单”属性与具有更大复杂性或一对多关系的属性之间存在明显的区别。
答案 2 :(得分:1)
两个原因存在__get
和__set
魔术方法:
这样您就不必花时间为所有属性创建vanilla访问器方法。
允许您实现属性重载。
如果你有需要特殊处理的属性,那么神奇的方法不适合你。但是,如果您的属性只包含数据并且没有依赖关系,则没有理由不使用魔术方法。
答案 3 :(得分:1)
此外,在本教程中,您可以修改__get()
和__set()
方法,以便了解它们为什么存在。
像这样的魔法处理可以让你做一些简洁的事情,比如甚至制作“只读”属性,并且可以防止你因为混乱的getter / setter而使你的课程膨胀。
答案 4 :(得分: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;
}
}
}