问题
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