12

考虑这个类:

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()了。

4

2 回答 2

12

__set对于给定的属性名称,每次尝试仅调用一次。 如果它(或它调用的任何东西)试图设置相同的属性,PHP 不会__set再次调用——它只会在对象上设置属性。

于 2012-04-04T19:24:20.837 回答
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不会被调用。

于 2012-04-04T19:19:06.183 回答