几天前,我花了一段时间调试了一个问题,并从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
)将被第二次打印。
回答你的问题。
那么,有人知道它为什么会这样吗?(有一些文档支持)
因为它是应该的。文档只是没有清楚地说明它是如何在类变量上运行的。
此外(需要文档),类变量是对值的引用,取消设置引用只会破坏引用,而不会破坏值(除非它是对该值的唯一引用)。
编辑:如果您对这个答案不满意,您可能会报告文档错误。