4

重複の可能性:
PHP はここで無限再帰をどのように回避しますか?

誰かがこれを php #wtf として Twitter に投稿しました:

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 がまだ存在しないため、おそらくコードに含まれていたものです。 in __get() が処理することになっています。PHP は無限再帰を自動検出し、そこで停止します。これは理にかなっていますが、一方、PHP は未定義のプロパティ A::$b に対してのみ E_NOTICE エラーを返します。

私の質問は、PHP が無限再帰を自動検出することは正しいですか? どうすればわかりますか?または、与えられた出力を説明する他の理由がありますか?

4

1 に答える 1

0

クラスでは、プライベート変数は非表示になりません。したがって、以下のコードを実行すると、__get() を呼び出さずに変数 $b を取得できます。

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 に答える