#php #массивы
PHP 5.6+. Имеется класс. class PropertyContainer { protected $_data; public $somePublicArray = [0]; public function __construct($data = []) { $this->_data = $data; } public function __get($name) { return array_key_exists($name, $this->_data) ? $this->_data[$name] : null; } public function __set($name, $value) { $this->_data[$name] = $value; } public function __unset($name) { unset($this->_data[$name]); } public function __isset($name) { return array_key_exists($name, $this->_data); } } Работа со свойствами класса происходит через магические методы и внутренний массив $_data, если свойство не объявлено в классе - довольно стандартный подход. И всё бы здорово, если бы не странный подход к оператору [] = в PHP: проводим тест $cont = new PropertyContainer(['a' => 1, 'b' => [0], 'c' => new ArrayObject ([0])]); $cont->a++; /*$cont->a = 2 OK*/ $cont->b[] = 1; /*$cont->b = [0] FAIL*/ $cont->somePublicArray[] = 1; /*$cont->somePublicArray = [0,1] OK*/ $cont->c[] = 1; /*$cont->c = ArrayObject [0,1] OK*/ var_dump($cont, is_array($cont->c)); die(); То есть массивы, содержащиеся внутри $_data возвращаются не по ссылке. Вопрос - какие есть способы это обойти, и использовать оператор [] = для заполнения внутренних массивов, кроме как массово использовать ArrayObject вместо array? С такой же проблеммой сталкивались , но эти решения не работают для хранения данных произвольных типов во внутреннем массиве (вроде $_data)- хотелось бы храннить данные в массиве (или ArrayObject) как есть. В использовании ArrayObject не нравится не срабатывания метода is_array() на нём, может быть можно переопределить поведение is_array ? Если использовать &__get вместо __get - можно ли вернуть указатель на элемент массива $_data ? Иначе будет просто варнинг Only variable references should be returned by reference .
Ответы
Ответ 1
Вариант 1: Если не нужна поддержка не объявляенных свойств: public function &__get($name) { if( array_key_exists($name, $this->_data) ) $val = &$this->_data[$name]; else $val = null; return $val; } В этом варианте есть баг: $cont = new PropertyContainer(['a' => 1, 'b' => [0]]); $cont->d[] = 1; // d не будет добавлено, вообще ничего не произойдёт. Вариант 2: Баг первого варианта исправлен, но _data будет захламлятся если есть попытки получать необъявляенные свойства. public function &__get($name) { if( ! array_key_exists( $name, $this->_data ) ){ $undefined; //It is possible to set default // value for every new parameter //Default is undefined. $this->_data[ $name ] = $undefined; } $val = &$this->_data[$name]; return $val; }
Комментариев нет:
Отправить комментарий