使用__set与数组解决,但为什么?

时间:2010-11-30 04:16:50

标签: php overloading getter-setter magic-methods

经过一些研究,我终于找到了一个问题的答案,我很快就会在这里提出这个问题;如何通过PHP中的__get__set魔术方法使用数组?每当我尝试使用类似$object->foo['bar'] = 42;之类的东西设置值时,它似乎默默地丢弃它。

无论如何,答案很简单; __get方法只需要通过引用返回。在将前面的&符号折腾之后,确实有效。

我的问题其实是,为什么?我似乎无法理解为什么这有效。 __get按引用返回如何影响使用多维数组的__set

编辑:顺便说一下,运行PHP 5.3.1

3 个答案:

答案 0 :(得分:4)

在PHP中,当您从函数返回值时,您可以认为它复制了该值(除非它是一个类)。在__get的情况下,除非您返回要编辑的实际内容,否则将对副本进行所有更改,然后将其丢弃。

答案 1 :(得分:3)

在这种特殊情况下,__set实际上并没有被调用。如果你打破它发生的事情,它应该更有意义:

$tmp = $object->__get('foo');
$tmp['bar'] = 42

如果__get未返回引用,则不是将42分配给原始对象的“bar”索引,而是分配给副本的“bar”索引

答案 2 :(得分:2)

可能更清楚:

//PHP will try to interpret this:
$object->foo['bar'] = 42

//The PHP interpreter will try to evaluate first 
$object->foo

//To do this, it will call 
$object->__get('foo')
// and not __get("foo['bar']"). __get() has no idea about ['bar']

//If we have get defined as &__get(), this will return $_data['foo'] element 
//by reference.
//This array element has some value, like a string: 
$_data['foo'] = 'value';

//Then, after __get returns, the PHP interpreter will add ['bar'] to that
//reference.
$_data['foo']['bar']

//Array element $_data['foo'] becomes an array with one key, 'bar'. 
$_data['foo'] = array('bar' => null)

//That key will be assigned the value 42
$_data['foo']['bar'] = 42

//42 will be stored in $_data array because __get() returned a reference in that
//array. If __get() would return the array element by value, PHP would have to 
//create a temporary variable for that element (like $tmp). Then we would make 
//that variable an array with $tmp['bar'] and assign 42 to that key. As soon 
//as php would continue to the next line of code, that $tmp variable would 
//not be used any more and it will be garbage collected.