w00*_*w00 53 php magic-methods
我知道这个问题已被问过好几次了,但是他们都没有一个真正的答案来解决这个问题.也许有一个针对我的具体案例.
我正在构建一个mapper类,它使用magic方法__get()来延迟加载其他对象.它看起来像这样:
public function __get ( $index )
{
if ( isset ($this->vars[$index]) )
{
return $this->vars[$index];
}
// $index = 'role';
$obj = $this->createNewObject ( $index );
return $obj;
}
Run Code Online (Sandbox Code Playgroud)
在我的代码中我做:
$user = createObject('user');
$user->role->rolename;
Run Code Online (Sandbox Code Playgroud)
这项工作到目前为止.该User对象没有名为"role"的属性,因此它使用magic __get()方法创建该对象,并从"role"对象返回其属性.
但是当我尝试修改'rolename'时:
$user = createUser();
$user->role->rolename = 'Test';
Run Code Online (Sandbox Code Playgroud)
然后它给我以下错误:
注意:间接修改重载属性无效
不确定这是否仍然是PHP中的一些错误,或者它是否是"预期的行为",但无论如何它都不能按我想要的方式工作.这对我来说真的是一个阻止......因为我怎么能改变延迟加载对象的属性?
编辑:
当我返回包含多个对象的数组时,似乎只会发生实际问题.
我添加了一个代码片段来重现问题:
你真的应该在你的PHP环境中运行它,真正看到'错误'.但这里有一些非常有趣的东西.
我试图改变一个对象的属性,这给了我通知'不能改变重载属性'.但是,如果我在之后回复该属性,我发现它实际上是DID改变了价值......真的很奇怪......
Vin*_*nyD 91
您需要做的就是在__get函数前添加"&"以将其作为参考传递:
public function &__get ( $index )
Run Code Online (Sandbox Code Playgroud)
挣扎了一段时间.
Bab*_*aba 16
很高兴你给了我一些可以玩的东西
跑
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;
Run Code Online (Sandbox Code Playgroud)
产量
test
test
w00
Run Code Online (Sandbox Code Playgroud)
使用的类
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 ;
}
}
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
产量
Ok die baba
Run Code Online (Sandbox Code Playgroud)
修改后的类
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 ;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 10
我有同样的错误,没有你的整个代码很难确切地指出如何解决它但它是由没有__set函数引起的.
我过去的方式是我做过这样的事情:
$user = createUser();
$role = $user->role;
$role->rolename = 'Test';
Run Code Online (Sandbox Code Playgroud)
现在如果你这样做:
echo $user->role->rolename;
Run Code Online (Sandbox Code Playgroud)
你应该看'测试'