假设我们有这段代码:
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->属性将首先尝试设置具有相同名称的公共属性,然后转到__get(),然后尝试调用公共方法setProperty(),然后转到__call( ),最后设置受保护的$ _property。
所以当我在我的代码中说某个地方时
$obj->property
我可以理解它首先尝试访问公共字段.. 为什么首先去__get()?为什么不__set()? 为什么它会转到__set()呢?
有人可以解释一下吗?感谢...
答案 0 :(得分:1)
__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']);
}
}