У меня есть следующий класс:
/**
* @property int $barMagic
*/
class Foo
{
public $barNormal;
private $attributes = [];
public function __get($name) {
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
}
public function __set($name, $value)
{
$this->attributes[$name] = $value;
}
}
Как видите, публичное свойство $ barMagic не определено явно, к нему можно получить доступ с помощью магических методов.
При установке, а затем изменении элемента массива в обычном атрибуте он работает нормально:
$foo = new Foo();
$foo->barNormal = ['baz' => 1];
echo $foo->barNormal['baz'];
$foo->barNormal['baz'] = 2;
echo ',' . $foo->barNormal['baz'];
Он выводит «1,2», как и предполагалось.
Но при использовании магического свойства оно не:
$foo = new Foo();
$foo->barMagic = ['baz' => 1];
echo $foo->barMagic['baz'];
$foo->barMagic['baz'] = 2;
echo ',' . $foo->barMagic['baz'];
Он выводит «1,1»!
Есть ли способ в PHP для доступа к элементам массива в магических свойствах так же, как обычные?
Интерфейс ArrayAccess, кажется, имеет дело с доступом к массиву на один уровень выше, чем мне нужно.
Реальный ответ хитрый и включает в себя некоторые ошибки / несоответствия в движке PHP. Как предложили комментаторы, я добавил&»(возврат по ссылке) перед символом __get (). Итак, новый код:
public function &__get($name) {
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
}
но это дает
Notice: Only variable references should be returned by reference in ....
Я должен был изменить это на
public function &__get($name) {
if (isset($this->attributes[$name])) {
return $this->attributes[$name];
} else {
return null;
}
}
и теперь это работает. Обратите внимание, что два фрагмента должны быть полностью эквивалентны, но это не так. Спасибо всем за вклад, вы взяли меня на полпути туда.
Других решений пока нет …