这里有一个难题:__set($value, $name)在匹配$obj->$key的setter存在时不被调用,但在它不


Here's a puzzler: __set($value, $name) not called when a setter matching $obj->$key exists, but is called when it doesn't

上下文:

$values = $form->getValues();
foreach($values as $key=>$value) {         
$obj->{$key} = $value;
}

如果$key是有效密钥,则不调用__set($name, $value)。如果$key不是有效密钥,则为有效密钥。下面是我的集合:

public function __set($name, $value) {
    $method = 'set' . ucfirst($name);
    if(method_exists($method)) {
        $this->$method($value);
    } else {
        throw new RuntimeException('Attempt to access a non-existant property with method ' . $method);
    }
}

__set($name, $value)方法所属的对象中,所有属性都是私有的并突出显示。因此,对于键'name',将有以下内容:

private $_name;
public function setName($name) {
    $this->_name = $name; 
    return $this; 
}

我知道它没有被调用,因为我试图在$method = 'set' . ucfirst($name);之后插入一个异常。当$name没有引用有效的setter时,会触发该异常,但当它没有引用时,不会触发该异常。它应该每次都被击中。有人知道这里发生了什么吗?

这是设计。从手册

__set()在向不可访问的属性写入数据时运行。

如果您有public属性匹配$key,它们将被设置,因为它们可访问

另外,您使用method_exists()是不正确的。应该是

if (method_exists($this, $method))

这是有记录的行为;这就是__set()的实际工作方式:文档在这里。