假设我们有以下代码:
class SomeClass{
private $somePrivateField;
public function __get($name){
$function = "get".ucfirst($name);
return $function;
}
public function __set($name,$value){
$function = "set".ucfirst($name);
return $function($value);
}
public function __call($name, $arguments) {
//if function being called is getSomething
//getThat private/protected field if exists and return
//if not raise exception
// similar for setSomething...
}
}
这是一些教程中的一段话:
__get() 方法接受表示要设置的属性的名称的参数。在 $obj->property 的情况下,参数将是属性。
然后,我们的 __get() 方法将其转换为 getProperty,这与我们在 __call() 方法中定义的模式相匹配。这意味着 $obj->property 将首先尝试设置一个同名的公共属性,然后转到 __get(),然后尝试调用公共方法 setProperty(),然后转到 __call(),最后设置受保护的 $_property。
所以当我在我的代码中的某个地方说
$obj->property
我可以理解它首先尝试访问公共领域。.为什么它首先转到__get()?为什么不__set()?那为什么它会转到 __set() 呢?
有人可以解释一下吗?谢谢。。。
-
__get()
只会返回一个字符串,其中包含可能不存在的函数的名称。 -
__set()
实际上调用了它构造名称的函数,但我无法确定原因,因为...... -
__call()
似乎必须确定它调用的函数实际上是"setter"还是"getter"函数,这首先是__get()
和__set()
的全部意义。 -
$obj->property
是一个无意义的代码片段,实际上不会自己做任何事情。
// assuming $obj->property is declared as private, or does not exist in the class.
$var = $obj->property; // invokes __get('property')
$obj->property = $var; // invokes __set('property', $var)
$obj->someFunction($var1, $var2, ...);
// invokes __call('someFunction', array($var1, $var2, ...)), but only if
// the specified function is private, or otherwise does not exist.
重写示例代码,使其具有某种意义:
class SomeClass{
private $somePrivateField;
public function __get($name){
if( isset($this->$name) ) {
return $this->$name;
} else {
Throw new Exception("Object property $name does not exist.");
}
}
public function __set($name,$value){
if( isset($this->$name) ) {
$this->$name = $value;
} else {
Throw new Exception("Object property $name does not exist.");
}
}
}
$obj = new SomeClass();
$obj->somePrivateField = $var; // uses __set()
$var = $obj->somePrivateField; // uses __get()
很少需要使用__call()
所有内容,对于给定的示例,当然不是。
或者,如果您希望能够设置/获取私有/公共属性,而无需先显式声明它们:
class SomeClass{
private $properties = array();
public function __get($name){
if( isset($this->properties['name']) ) {
return $this->properties['name'];
} else {
Throw new Exception("Object property $name does not exist.");
}
}
public function __set($name,$value){
$this->properties[$name] = $value;
}
// it's also a good idea to define __isset() and __unset() in this case as well
public function __isset($name) {
return isset($this->properties['name']);
}
public function __unset($name) {
return unset($this->properties['name']);
}
}