__set __get的顺序是什么,访问公共字段和__call?

时间:2013-01-30 18:54:36

标签: php get set call magic-methods

假设我们有这段代码:

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()呢?

有人可以解释一下吗?感谢...

1 个答案:

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