PHP如何避免无限递归?

时间:2012-04-04 19:13:50

标签: php recursion getter-setter

考虑这个课程:

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的魔术__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()

2 个答案:

答案 0 :(得分:12)

__set is only called once per attempt for a given property name.如果它(或它调用的任何东西)试图设置相同的属性,PHP将不会再次调用__set - 它只会在对象上设置属性。

答案 1 :(得分:2)

来自documentation

  将数据写入无法访问的属性

时,会运行

__ 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