我知道这个问题已经被问了好几次,但他们都没有的解决方法,一个真正的答案。 也许有一个我的具体情况。
我建立它使用魔术方法的映射器类__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
对象没有一个叫“角色”属性,所以它使用的魔法__get()
方法来创建对象,并将其从“角色”对象返回其属性。
但是,当我试图修改“角色名”:
$user = createUser();
$user->role->rolename = 'Test';
然后,它给了我下面的错误:
注意:超载财产的间接改变没有影响
不知道这仍是在PHP一些bug,或者如果它的“预期的行为”,但在任何情况下,它不工作,我想要的方式。 这真是对我来说是表演塞...因为如何在地球上我能够改变延迟加载对象的属性?
编辑:
实际的问题似乎只当我返回一个包含多个对象的数组发生。
我已经添加的示例代码片段其再现的问题:
http://codepad.org/T1iPZm9t
你应该运行这个在你的PHP环境中真正看到了“错误”。 但也有一些是非常有趣的事情在这里。
我试图改变一个对象,这给我的通知“不能改变重载财产”的财产。 但是,如果我以后呼应财产我看到,它实际上没有改变数值...很奇怪...
很高兴你给我的东西一起玩
跑
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 ;
}
}
所有你需要做的就是添加“&”你__get函数的前面把它作为参考:
public function &__get ( $index )
挣扎与这一个了一段时间。
我有同样的错误,没有你的整个代码也很难查出究竟如何解决它,但它是由不具有__set功能引起的。
我已经在过去的四周得到的方式是我做了这样的事情:
$user = createUser();
$role = $user->role;
$role->rolename = 'Test';
现在,如果你这样做:
echo $user->role->rolename;
你应该看到“测试”
虽然我在此讨论很晚了,我认为这可能是有人在将来有用。
我曾面临类似的情况。 对于那些谁不介意和解封重置变量最简单的解决方法是这样做的。 我敢肯定,这是为什么不工作的原因是从其他的答案,并从php.net手动清除。 工作对我来说,最简单的解决方法是
假设:
-
$object
是重载的对象__get
和__set
从基类,这是我的自由修改我不是。 -
shippingData
是我想修改为如现场数组: - PHONE_NUMBER
// First store the array in a local variable.
$tempShippingData = $object->shippingData;
unset($object->shippingData);
$tempShippingData['phone_number'] = '888-666-0000' // what ever the value you want to set
$object->shippingData = $tempShippingData; // this will again call the __set and set the array variable
unset($tempShippingData);
注意:此方法是快速的解决方法可以解决这个问题,并得到复制的变量之一。 如果数组太小humungous,它有良好的可强制改写__get
方法返回大阵列的参考相当昂贵的复制。
我收到此通知这样做的:
$var = reset($myClass->my_magic_property);
这个固定:
$tmp = $myClass->my_magic_property;
$var = reset($tmp);
这是它们不修改或通过引用传递发生由于PHP对待如何重载在于性质。
请参阅手册的有关超载的更多信息。
要解决这个问题,你可以使用一个__set
函数或创建createObject
方法。
下面是一个__get
和__set
,提供了一个解决方法,以类似的情况,以你的,你可以简单地修改__set
适合您的需求。
注意__get
实际上从未返回变量。 和而一旦你在你的对象设置变量不再超载。
/**
* Get a variable in the event.
*
* @param mixed $key Variable name.
*
* @return mixed|null
*/
public function __get($key)
{
throw new \LogicException(sprintf(
"Call to undefined event property %s",
$key
));
}
/**
* Set a variable in the event.
*
* @param string $key Name of variable
*
* @param mixed $value Value to variable
*
* @return boolean True
*/
public function __set($key, $value)
{
if (stripos($key, '_') === 0 && isset($this->$key)) {
throw new \LogicException(sprintf(
"%s is a read-only event property",
$key
));
}
$this->$key = $value;
return true;
}
这将允许:
$object = new obj();
$object->a = array();
$object->a[] = "b";
$object->v = new obj();
$object->v->a = "b";
我遇到了同样的问题,W00,但我并没有自由改写在这个问题(E_NOTICE)发生组件的基本功能。 我已经能够解决使用问题ArrayObject的在基本型代替阵列() 。 这将返回一个对象,这将defaulty通过引用返回。