问题
Consider this class:
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;
}
}
I am overloading PHP's magic __set() method. Whenever I set a property in an object of the test
class, it will call __set()
, which in turn calls other_set()
.
$obj = new test;
$test->prop = 10;
/* prints the following */
__set() called
other_set() called
But other_set()
has the following line $this->$name = $value
. Shouldn't this result in a call to __set()
, causing infinite recursion?
I theorized that it would call __set()
only when setting things outside the class. But if you call the method t()
you can see it clearly goes through __set()
too.
回答1:
__set is only called once per attempt for a given property name. If it (or anything it calls) attempts to set the same property, PHP won't call __set
again -- it'll just set the property on the object.
回答2:
From the documentation:
__set() is run when writing data to inaccessible properties
For example:
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 this case, $x->prop
is inaccessible and __set
will be called. $x->attributes
is also inaccessible, so __set
will be called. However, $x->bar
is publicly accessible, so __set
will not be called.
Similarly, in the __set
method, $this->attribtues
is accessible, so there is no recursion.
In your example code above, $this->$name
is accessible in the scope in which its called, therefore __set
is not called.
来源:https://stackoverflow.com/questions/10017741/how-does-php-avoid-infinite-recursion-here