2012-04-04 10 views
12

Betrachten Sie diese Klasse:Wie vermeidet PHP hier unendliche Rekursion?

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; 
    } 
} 

ich PHP Magie __set() Methode bin überlasten. Immer wenn ich eine Eigenschaft in einem Objekt der Klasse test einstelle, wird sie __set() aufrufen, die wiederum other_set() aufruft.

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

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

Aber other_set() hat die folgende Zeile $this->$name = $value. Sollte dies nicht zu einem Aufruf von __set() führen, was zu einer unendlichen Rekursion führt?

Ich theoretisierte, dass es __set() nur aufrufen würde, wenn Dinge außerhalb der Klasse gesetzt werden. Aber wenn Sie die Methode t() aufrufen, können Sie sehen, dass es auch __set() übertrifft.

Antwort

11

__set is only called once per attempt for a given property name. Wenn es (oder irgendetwas, das es anruft) versucht, dieselbe Eigenschaft zu setzen, wird PHP __set nicht erneut aufrufen - es wird nur die Eigenschaft für das Objekt festgelegt.

+0

Das ist richtig. Wenn jemand die Implementierungsdetails sehen möchte, ist es in 'zend_object_handlers.c'. – Confluence

+0

@Confluence: Danke ... ich habe mich gefragt, wo ich das gelesen habe. :) Konnte es nicht im Handbuch finden; Ich begann mich zu fragen, ob ich es mir vorgestellt hatte. Aber alle meine Tests bestätigten es, also ... – cHao

+0

Diese Antwort war SO nützlich! –

2

Vom documentation:

__set() ausgeführt wird, wenn Daten in unzugänglichen Eigenschaften Schreiben

Zum Beispiel:

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"; 

In diesem Fall $x->prop ist unzugänglich und __set wird aufgerufen. $x->attributes ist auch nicht erreichbar, daher wird __set aufgerufen werden. $x->bar ist jedoch öffentlich zugänglich, so __set wird nicht genannt werden.

In ähnlicher Weise ist in der __set Methode $this->attribtues zugänglich, so dass es keine Rekursion gibt.

In Ihrem obigen Beispielcode ist $this->$name in dem Bereich zugänglich, in dem es aufgerufen wird, daher wird __set nicht aufgerufen.

+0

Was macht Unterschied? – Confluence

+0

@Confluence die Eigenschaft ist nicht zugänglich innerhalb der Klasse selbst .. – TZHX

+0

@TZHX Unzugänglich kann bedeuten, nicht sichtbar oder nicht deklariert. Auf alle Eigenschaften kann per Definition nicht zugegriffen werden, da ich keine deklarierten Eigenschaften habe. – Confluence

Verwandte Themen