2012-04-04 14 views
12

は、このクラスを考えてみましょう:ここでPHPは無限回帰を避けますか?

class test 
{ 
    public function __set($n, $v) 
    { 
     echo "__set() called\n"; 
     $this->other_set($n, $v, true); 
    } 

    public function other_set($name, $value) 
    { 
     echo "other_set() called\n";  
     $this->$name = $value; 
    } 

    public function t() 
    { 
     $this->t = true; 
    } 
} 

私はPHPのマジック__set()メソッドをオーバーロードしています。 testクラスのオブジェクトにプロパティを設定するたびに__set()が呼び出され、other_set()が呼び出されます。

$obj = new test; 
$test->prop = 10; 

/* prints the following */ 
__set() called 
other_set() called 

しかしother_set()次の行$this->$name = $valueを持っています。これにより、無限再帰を引き起こす__set()が呼び出されるべきではありませんか?

私は、クラス外のものを設定するときにのみ__set()を呼び出すと理論化しました。しかし、あなたがt()メソッドを呼び出す場合は、明らかにそれが__set()を通過することがわかります。

答えて

11

__set is only called once per attempt for a given property name.同じプロパティを設定しようとすると、PHPは__setを再度呼び出すことはありません。オブジェクトにプロパティを設定するだけです。

+0

これは正しいです。実装の詳細を見たい人は、 'zend_object_handlers.c'にあります。 – Confluence

+0

@影響:ありがと...私はそれをどこで読んでいるのだろうと思っていた。 :)マニュアルでそれを見つけることができませんでした。私はそれが想像していたのだろうかと思っていた。しかし、すべての私のテストはそれを確認したので... – cHao

+0

この回答は役に立ちました! –

2

documentationから:この場合、

class foo { 
    private $attributes; 
    public $bar; 

    public function __construct() { 
    $this->attributes = array(); 
    } 

    public function __set($n, $v) { 
    echo "__set() called\n"; 
    $this->attributes[$n] = $v; 
    } 
} 

$x = new foo; 
$x->prop = "value"; 
$x->attributes = "value"; 
$x->bar = "hello world"; 

$x->propはアクセスできない:

__set()例えばアクセスできない特性

にデータを書き込むときに実行されます__setが呼び出されます。 $x->attributesもアクセスできないので、__setが呼び出されます。ただし、$x->barには公開されていますので、__setとなり、と呼ばれることはありません。

同様に、__setの方法では、$this->attribtuesにアクセスできるため、再帰はありません。

上記の例のコードでは、$this->$nameは呼び出されたスコープでアクセス可能であるため、__setは呼び出されません。

+0

違いは何ですか? – Confluence

+0

@Confluenceクラス自体の中からプロパティにアクセスできません。 – TZHX

+0

@TZHXアクセスできないとは、可視でないか、宣言されていないことを意味します。私は宣言されたプロパティがないので、すべてのプロパティは定義によってアクセスできません。 – Confluence

関連する問題