Рассмотрим этот класс:
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()
.
__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
не вызывается.