Подтвердить что ты не робот

Как 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 magic __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().

4b9b3361

Ответ 2

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

__ 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 будет вызываться не.

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

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