为什么从类中取消设置var的结果不一致


Why unseting a var from a class have inconsistent resuls

几天前,我花了一段时间调试了一个问题,并从unset()类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()返回:

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,则会引起"未定义变量"通知。为了澄清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文档状态:

根据作用域获取给定对象的可访问非静态属性。

__set,文档状态:

在将数据写入不可访问的属性时运行。

unset(),文档状态:

破坏指定的变量

由此,我得出结论"destroys"="make variable invalidable",因为如果unset除了使其不可访问之外,还做了其他任何操作,那么[var] =>(或[var] =>NULL)将被第二次打印。

回答你的问题。

那么,有人知道它为什么会这样吗?(有一些文档支持)

因为它是应该的。文档只是没有清楚地说明它是如何在类变量上运行的。

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

编辑:如果您对这个答案不满意,您可能会报告文档错误。