我知道这个问题已经被问过几次了,但是他们都没有真正的解决方法。对于我的具体情况,也许有一个。
我正在构建一个映射器类,该映射器类使用magic方法__get()来延迟加载其他对象。看起来像这样:
__get()
public function __get ( $index ) { if ( isset ($this->vars[$index]) ) { return $this->vars[$index]; } // $index = 'role'; $obj = $this->createNewObject ( $index ); return $obj; }
在我的代码中,我这样做:
$user = createObject('user'); $user->role->rolename;
到目前为止,该方法有效。该User对象没有名为“ role”的属性,因此它使用magic __get()方法创建该对象,并从“ role”对象返回其属性。
User
但是当我尝试修改’rolename’时:
$user = createUser(); $user->role->rolename = 'Test';
然后它给了我以下错误:
注意:间接修改重载属性无效
不知道这是否仍然是PHP中的某个bug还是“预期的行为”,但是无论如何它都不符合我想要的方式。对我来说,这确实是一个表演的终结者。。。因为我到底能如何改变延迟加载对象的属性?
编辑:
当我返回包含多个对象的数组时,似乎只会出现实际问题。
我添加了一个示例代码来重现该问题:
http://codepad.org/T1iPZm9t
您应该在PHP环境中真正运行此程序,才能真正看到“错误”。但是这里确实发生了一些有趣的事情。
我尝试更改对象的属性,这使我注意到“无法更改重载属性”。但是如果我在之后回显该属性,我会发现它实际上是DID更改了值…真的很奇怪…
很好,你给了我一些玩的东西
跑
class Sample extends Creator { } $a = new Sample (); $a->role->rolename = 'test'; echo $a->role->rolename , PHP_EOL; $a->role->rolename->am->love->php = 'w00'; echo $a->role->rolename , PHP_EOL; echo $a->role->rolename->am->love->php , PHP_EOL;
输出量
test test w00
使用的班级
abstract class Creator { public function __get($name) { if (! isset ( $this->{$name} )) { $this->{$name} = new Value ( $name, null ); } return $this->{$name}; } public function __set($name, $value) { $this->{$name} = new Value ( $name, $value ); } } class Value extends Creator { private $name; private $value; function __construct($name, $value) { $this->name = $name; $this->value = $value; } function __toString() { return (string) $this->value ; } }
class Sample extends Creator { } $a = new Sample (); $a->role = array ( "A", "B", "C" ); $a->role[0]->nice = "OK" ; print ($a->role[0]->nice . PHP_EOL); $a->role[1]->nice->ok = array("foo","bar","die"); print ($a->role[1]->nice->ok[2] . PHP_EOL); $a->role[2]->nice->raw = new stdClass(); $a->role[2]->nice->raw->name = "baba" ; print ($a->role[2]->nice->raw->name. PHP_EOL);
Ok die baba
改良班
abstract class Creator { public function __get($name) { if (! isset ( $this->{$name} )) { $this->{$name} = new Value ( $name, null ); } return $this->{$name}; } public function __set($name, $value) { if (is_array ( $value )) { array_walk ( $value, function (&$item, $key) { $item = new Value ( $key, $item ); } ); } $this->{$name} = $value; } } class Value { private $name ; function __construct($name, $value) { $this->{$name} = $value; $this->name = $value ; } public function __get($name) { if (! isset ( $this->{$name} )) { $this->{$name} = new Value ( $name, null ); } if ($name == $this->name) { return $this->value; } return $this->{$name}; } public function __set($name, $value) { if (is_array ( $value )) { array_walk ( $value, function (&$item, $key) { $item = new Value ( $key, $item ); } ); } $this->{$name} = $value; } public function __toString() { return (string) $this->name ; } }