Как 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; } } 

Я перегружаю магический __set() PHP. Всякий раз, когда я устанавливаю свойство в объекте 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() , вызывающему бесконечную рекурсию?

Я предположил, что он будет называть __set() только при настройке вещей вне класса. Но если вы __set() метод t() вы увидите, что он явно проходит через __set() .

    Related of "Как PHP избегает бесконечной рекурсии?"

    __set вызывается только один раз за попытку для данного имени свойства. Если он (или все, что он вызывает) пытается установить одно и то же свойство, PHP не будет вызывать __set снова – он просто установит свойство на объект.

    Из документации :

    __set () запускается при записи данных в недоступные свойства

    Например:

     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 . $x->attributes также недоступны, поэтому будет вызываться __set . Тем не менее, $x->bar является общедоступным, поэтому __set не будет вызван.

    Аналогично, в методе $this->attribtues доступно $this->attribtues , поэтому нет рекурсии.

    В приведенном выше примере кода $this->$name доступно в области, в которой его __set , поэтому __set не вызывается.