0
<?php
class BaseClass {
  protected $data = array("foo" => 0, "bar" => 0, "baz" => 0);

  public function __set($name, $value) {
    if( array_key_exists($name, $this->data)){
      $func = "set_$name";
      return call_user_func_array(array($this,$func),array($value));
    }
  }


  public function __get($name) {
    if ( array_key_exists($name, $this->data)){
      $func = "get_$name";
      return call_user_func_array(array($this,$func),array());
    }
  }

  public function __call($method, $args) {
    if (method_exists($this,$method)) {
      return call_user_func_array(array($this,$method),$args);
    }

    if (substr($method, 0, 4) == 'set_'){
      $var_name = substr($method, 4);
      if (!(array_key_exists($var_name, $this->data))){ 
        return FALSE;
      }
      $this->data[$var_name] = $args[0];
      return TRUE;
    }

    if (substr($method, 0, 4) == 'get_'){
      $var_name = substr($method, 4);
      if (!(array_key_exists($var_name, $this->data))){ 
        return FALSE;
      }
      return $this->data[$var_name];
    }
  }
}

class SubClass extends BaseClass {
  protected $baz_changed = FALSE;

  public function set_baz($value) {
    if ($value != $this->baz){
      print "\n\nthis->data BEFORE SET:  ";
      print_r($this->data);
      print "\n\nthis->baz:  ";
      print_r($this->baz);
      print "\n\nPASSED baz:  ";
      print_r($value);
      $this->baz = $value;
      print "\n\nbaz AFTER SET:  ";
      print_r($this->baz); // appears it was set 
      print "\n\nDATA ARRAY:  ";
      print_r($this->data);  // but it wasn't ... what gives? 
      $this->baz_changed = TRUE;
    }
  }
}

$sc = new SubClass();
$sc->foo = 1;
print "\n\$sc->foo = $sc->foo\n";
$sc->baz = 5;
print "\$sc->baz = $sc->baz\n";
?>

我得到以下结果并不像我预期的那样:

 $sc->foo = 1


 this->data BEFORE SET:  Array (
     [foo] => 1
     [bar] => 0
     [baz] => 0 )


 this->baz:  0

 PASSED baz:  5

 baz AFTER SET:  5

 DATA ARRAY:  Array (
     [foo] => 1
     [bar] => 0
     [baz] => 0 ) $sc->baz = 5

如您所见,似乎 baz 已设置,但从未在数据数组中设置。谁能解释为什么以及如何解决这个问题?

编辑:修复了结果的格式并为此代码部分添加了更多上下文,因为 stackoverflow 抱怨我没有足够的。

编辑:刚刚注意到最后它说 $sc->baz = 5。但是数据数组没有更新。这不是预期的,我宁愿更新 baz 的数据数组版本。而不是在 SubClass 中创建新的实例变量。

4

2 回答 2

2

您正在尝试递归调用__set,而 PHP 明确禁止这样做。

  • __set中,您调用set_baz
  • set_baz,你做$this->baz = 5
  • 这将调用__set,除非 PHP 阻止这种情况发生。如果没有,您的程序将永远不会结束。

__set如果您已经在 内,则无法触发__set。相反,您正在动态定义一个新的成员变量,该成员变量的调用$this->baz方式就像__set不存在一样。如果你是var_dump你的对象,你会发现它现在同时包含$data$baz成员。

在内部set_baz,您需要显式写入$this->data. 您不能写入$this->baz.

于 2012-08-16T05:23:38.793 回答
0

它的行为正确,当你这样做$sc->baz = 5;时发现 set_baz 方法在那里并执行这一行$this->baz = $value;并设置 baz 属性的值

假设如果 __get 和 __set 也在课堂上工作,那么你如何在课堂上访问 $this->data ?

于 2012-08-16T05:25:13.997 回答