1

__set()我有两个使用和__get()魔术方法的简单类示例。unset()尝试使用该函数访问受保护的属性时,一个会引发致命错误,而另一个不会。

在示例 1 中,我将我的受保护属性命名为以下划线开头,并允许通过友好名称进行访问,并在我的__set()and__get()方法中添加下划线。(有效地暴露属性而没有下划线)。

在示例 2 中,我没有使用下划线开头的名称并允许直接在__set()and__get()方法中通过名称进行访问。

问题

1) 为什么示例 1不会引发致命错误,而示例 2引发致命错误?我希望要么都抛出错误,要么都不抛出错误。

2)另外,为什么示例 1实际上没有取消设置属性?我希望该属性在unset()调用函数后不包含值。

示例 1

class Example {

    protected $_my_property;

    function __get($name) {
        echo '<h4>__get() was triggered!</h4>';
        $name = '_' . $name;
        if (property_exists($this, $name)) {
            return $this->$name;
        }
        else {
            trigger_error("Undefined property in __get(): $name");
            return NULL;
        }
    }

    function __set($name, $value) {
        echo '<h4>__set() was triggered!</h4>';
        $name = '_' . $name;
        if (property_exists($this, $name)) {
            $this->$name = $value;
            return;
        }
        else {
            trigger_error("Undefined property in __set(): {$name}");
        }
    }

}

$myExample = new Example();
$myExample->my_property = 'my_property now has a value';
echo $myExample->my_property;
unset($myExample->my_property);
echo "Did I unset my property?: {$myExample->my_property}";

示例 2

class Example {

    protected $my_property;

    function __get($name) {
        echo '<h4>__get() was triggered!</h4>';
        if (property_exists($this, $name)) {
            return $this->$name;
        }
        else {
            trigger_error("Undefined property in __get(): $name");
            return NULL;
        }
    }

    function __set($name, $value) {
        echo '<h4>__set() was triggered!</h4>';
        if (property_exists($this, $name)) {
            $this->$name = $value;
            return;
        }
        else {
            trigger_error("Undefined property in __set(): {$name}");
        }
    }

}

$myExample = new Example();
$myExample->my_property = 'my_property now has a value';
echo $myExample->my_property;
unset($myExample->my_property);
echo "Did I unset my property?: {$myExample->my_property}";

作为旁注,这只是一个简单的示例,展示了我在现实世界项目中看到的行为。谢谢!

4

1 回答 1

2

你遇到的问题是你没有定义一个__unset()魔法方法。

这意味着当您调用 时unset($myExample->my_property),它会尝试直接取消设置具有指定名称的公共属性。

在示例 1 中,真正的受保护属性的名称中有一个下划线。因此,当您尝试取消设置该属性时,PHP 会查看该对象,发现没有任何具有指定名称的内容,并有效地忽略它。

unset()如果您尝试取消设置不存在的变量或数组元素,则会出现相同的行为。

unset()但是在示例 2 中,受保护的属性与您在调用中给出的名称相同。

在这个例子中,PHP 查看对象并看到该属性确实存在,但它是不可访问的。因此,它会抛出一个错误,抱怨它无法取消设置该属性。

您可以通过在和__unset()方法旁边包含一个方法来解决此问题。如果您打算使用魔术方法,则最好定义所有这三个方法。__get()__set()

希望有帮助。

于 2013-09-04T15:30:19.863 回答