__set __get的顺序是什么,访问公共领域和__call


What is the order of __set __get, accessing a public field and __call?

假设我们有以下代码:

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']);
    }
}