2010-11-30 5 views
5

Después de investigar un poco, finalmente encontré la respuesta a una pregunta que pronto iba a preguntar aquí; ¿Cómo se trabaja con arrays a través de los métodos mágicos __get y __set en PHP? Cada vez que intentaba establecer un valor usando algo como $object->foo['bar'] = 42;, parecía descartarlo silenciosamente.Usando __set con matrices resueltas, pero ¿por qué?

De todos modos, la respuesta es simple; El método __get simplemente tiene que regresar por referencia. Y después de lanzar un signo de unión delante de él, por supuesto, funciona.

Mi pregunta es, ¿por qué? No puedo entender por qué esto está funcionando. ¿Cómo afecta el __get que regresa por referencia a __set trabajar con matrices multidimensionales?

Editar: Por cierto, se ejecuta PHP 5.3.1

+0

Al parecer, en la toma de PHP 5.2.x __get devolver una referencia no ayuda. – Vlad

Respuesta

3

En este caso particular, __set no recibe ninguna llamada. Si usted analiza lo que esto ocurra, se debe hacer un poco más de sentido:

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

Si __get no arrojó una referencia, a continuación, en lugar de asignar 42 para indexar la 'barra' del objeto original, eres asignar al índice 'bar' de una copia del objeto original.

+0

Gracias ** Dean **; Lo tengo :) – Dan

4

En PHP cuando regrese un valor de una función se puede considerar que se hace una copia de ese valor (a menos que sea una clase). En el caso de __get a menos que devuelva la cosa real que desea editar, todos los cambios se realizan en una copia que luego se descarta.

+0

Ah, ¿en el proceso de establecer un valor, antes de llamar a '__set', se llama a' __get' para recuperar (o verificar) la existencia de la variable objeto? – Dan

+1

'$ object-> foo ['bar'] = 42;' never calls set. Se llama a Set cuando haces algo como '$ object-> key = $ value', pero no cuando haces' $ object-> key [$ key2] = $ value'. Esto se debe a que '$ object-> key [$ key2]' se resuelve usando '__get' y luego se altera. Entonces puedes pensarlo como '$ magic_get_value = $ value'. –

2

tal vez más claro:

//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. 
Cuestiones relacionadas