Использование __set с массивами решено, но почему? - PullRequest
5 голосов
/ 30 ноября 2010

Проведя небольшое исследование, я, в конце концов, наткнулся на ответ на вопрос, который мне скоро придется здесь задать; Как вы работаете с массивами с помощью магических методов __get и __set в PHP? Всякий раз, когда я пытался установить значение, используя что-то вроде $object->foo['bar'] = 42;, казалось, что оно молча сбрасывает его.

В любом случае, ответ прост; Метод __get просто необходимо вернуть по ссылке. И после того, как он бросил перед ним амперсанд, он наверняка сработает.

Мой вопрос на самом деле, почему? Я не могу понять, почему это работает. Как __get возврат по ссылке влияет на __set работу с многомерными массивами?

Редактировать: Кстати, работает PHP 5.3.1

Ответы [ 3 ]

4 голосов
/ 30 ноября 2010

В PHP, когда вы возвращаете значение из функции, вы можете сделать копию этого значения (если это не класс).В случае __get, если вы не вернете фактическую вещь, которую хотите отредактировать, все изменения будут внесены в копию, которая затем отбрасывается.

3 голосов
/ 30 ноября 2010

В данном конкретном случае __set на самом деле не вызывается. Если вы разобьетесь в том, что происходит, это должно иметь больше смысла:

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

Если __get не вернул ссылку, тогда вместо присвоения 42 индексу 'bar' исходного объекта, вы будете присваивать индекс 'bar' копии из оригинальный объект.

2 голосов
/ 02 июля 2012

может быть, более ясно:

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