为什么从 class 取消设置汽车会产生不一致的结果

Why unseting a var from a class have inconsistent resuls

几天前,我花了一些时间来调试一个问题,并从 unset() class vars 和 magic __set() 方法中发现了奇怪的行为。

事情是这样的:

class A {
    public $var;

    public function unsetVar() {unset($this->var);}
}

class B extends A {
    public $attr = array();
    public function __set($key, $value) {$this->attr[$key] = $value;}
}

$a = new A();
$a->unsetVar();
$a->var = 'teste';

$b1 = new B();
$b1->var = 'teste';

$b2 = new B();
$b2->unsetVar();
$b2->var = 'teste';

var_dump($a, $b1, $b2);

php在线示例:http://goo.gl/CO3Uxj

那 var_dump() returns:

object(A)#1 (1) {
  ["var"]=>
  string(5) "teste"
}
object(B)#2 (1) {
  ["attr"]=>
  array(1) {
    ["var"]=>
    string(5) "teste"
  }
}

因此,如果取消 $a->var 的设置,那么重新设置将按预期工作,只是为了确保 $b1->var 将设置 var 而不会触发魔术方法,但是当我们在 b2 处取消设置时var,那么魔术方法将被触发而不是重置 $b2->var.

首先我认为内部 PHP 会使用魔术方法 __set() 来设置未设置的变量,方法是使用反射或一些内部方法来检查 属性 是否存在.

所以因为我已经覆盖了 __set() 它会执行我的,但没有找到任何支持它的东西。

所以,有谁知道它为什么会这样? (有一些文档支持)

谢谢大家!

unset($var) 破坏了变量 $var,使其无法访问,如果您再次尝试使用 $var 会导致 'undefined variable' 通知。澄清 unset() 破坏了 variable,而不是 value。销毁变量意味着它将不再存在(可访问)。

我找不到明确说明这一点的文档,但以下测试支持我的主张(您对 __set 的测试也是如此)。

我做了以下说明 __unset() 实际上使变量不可访问:

class x {
    public $var;
}
$x = new x();
  echo '<pre>';
print_r(get_object_vars($x)); //prints Array([var] =>)
      echo '<br>';
unset($x->var); //prints Array()
print_r(get_object_vars($x));

因此,get_object_vars 文档状态:

Gets the accessible non-static properties of the given object according to scope.

__set,文档状态:

is run when writing data to inaccessible properties.

unset(),文档状态:

destroys the specified variables

我从中得出结论 'destroys' = 'make variable inaccessible' 因为如果 unset 除了使其无法访问之外做了任何其他事情,那么 [var] =>(或 [var] =>NULL)会打印第二次。

回答你的问题。

So, does anyone know why it behaves like this? (with some docs to support)

因为它应该。文档只是没有明确说明它如何在 class 变量上运行。

此外(需要文档),class 变量是对值的引用,取消设置引用只会破坏引用而不是值(除非它是对值的唯一引用)。

编辑:如果您对这个答案不满意,您可以report a documentation bug