<?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 的数据数组版本。 而不是在子类中创建的新实例变量。
你试图递归调用__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
.
它的行为正确,当你这样做时$sc->baz = 5;
它会发现set_baz方法在那里并执行此行$this->baz = $value;
并设置 baz 属性的值
假设如果__get和__set也在类中工作,那么您如何访问类中的$this>数据?