4

可能的重复:
PHP 如何在这里避免无限递归?

有人在 Twitter 上将此作为 php #wtf 发布:

class A
{
    private $b;

    function __construct()
    {
        unset($this->b);
    }

    function __get($n)
    {
        echo '!broken!';
        return $this->$n;
    }
}

$a = new A;
$a->b; //EDIT: original question had var_dump($a->b);

//output:
!broken!!broken!

我对此的第一反应是 $a->b 为第一个回显触发 __get() ,然后返回 $this->$n 再次触发 __get 导致 $this->b 仍然不存在,这大概是包含的代码在 __get() 应该处理。PHP 自动检测无限递归并停在那里。这是有道理的,但另一方面,PHP 只对欠精细的属性 A::$b 给出 E_NOTICE 错误。

所以我的问题是,我对 PHP 自动检测无限递归是否正确?我怎么知道?还是有其他原因来解释给出的输出?

4

1 回答 1

0

在类中,私有变量没有隐藏。因此,在执行以下代码时,您可以获取变量 $b,而无需调用 __get():

class A {
  private $b;
  function get_b()
  {
      return $this->b;    
      }
 }

$a = new A; 
echo $a->get_b();

但在下面的一个中,你不能 - 它会调用函数 __get():

class A 
{
    private $b;
    function get_b()
    {
        return $this->b;    
        }

}

 $a = new A; echo $a->b;

所以在你的例子中:

A类{私人$ b;

function __construct()
{
    unset($this->b);
}

function __get($n)
{
    echo '!broken!';
    return $this->$n;
} 
}
$a = new A; // Here you called unset, and since it doesn't know the "b", it calls __get().
var_dump($a->b); // Again here $a->b is not "exists" or "hidden", so it calls __get() again. 

在 __get() 中,“return $this->$n”确实知道变量 $n - 也就是说 $b (就像在我的第一个代码示例中 - 函数 get_b() )。所以它实际上不是无限递归,它就像任何其他函数调用一样;)

于 2012-11-11T10:19:22.267 回答