С примером такого класса:
class Test{ public function &__get($name){ print_r($name); } }
Экземпляр Test
отбросит результат как таковой:
$myTest = new Test; $myTest->foo['bar']['hello'] = 'world'; //outputs only foo
Есть ли способ получить дополнительную информацию о том, какое измерение массива будет доступно, показывая мне (из предыдущего примера), что элемент bar
из foo
и элемент hello
bar
нацелены?
Вы не можете с текущей реализацией. Чтобы это сработало, вам нужно будет создать объект массива (т. ArrayAccess
Объект, реализующий ArrayAccess
). Что-то вроде:
class SuperArray implements ArrayAccess { protected $_data = array(); protected $_parents = array(); public function __construct(array $data, array $parents = array()) { $this->_parents = $parents; foreach ($data as $key => $value) { if (is_array($value)) { $value = new SuperArray($value, array_merge($this->_parents, array($key))); } $this[$key] = $value; } } public function offsetGet($offset) { if (!empty($this->_parents)) echo "['".implode("']['", $this->_parents)."']"; echo "['$offset'] is being accessed\n"; return $this->_data[$offset]; } public function offsetSet($offset, $value) { if ($offset === '') $this->_data[] = $value; else $this->_data[$offset] = $value; } public function offsetUnset($offset) { unset($this->_data[$offset]); } public function offsetExists($offset) { return isset($this->_data[$offset]); } } class Test{ protected $foo; public function __construct() { $array['bar']['hello'] = 'world'; $this->foo = new SuperArray($array); } public function __get($name){ echo $name.' is being accessed.'.PHP_EOL; return $this->$name; } } $test = new Test; echo $test->foo['bar']['hello'];
сclass SuperArray implements ArrayAccess { protected $_data = array(); protected $_parents = array(); public function __construct(array $data, array $parents = array()) { $this->_parents = $parents; foreach ($data as $key => $value) { if (is_array($value)) { $value = new SuperArray($value, array_merge($this->_parents, array($key))); } $this[$key] = $value; } } public function offsetGet($offset) { if (!empty($this->_parents)) echo "['".implode("']['", $this->_parents)."']"; echo "['$offset'] is being accessed\n"; return $this->_data[$offset]; } public function offsetSet($offset, $value) { if ($offset === '') $this->_data[] = $value; else $this->_data[$offset] = $value; } public function offsetUnset($offset) { unset($this->_data[$offset]); } public function offsetExists($offset) { return isset($this->_data[$offset]); } } class Test{ protected $foo; public function __construct() { $array['bar']['hello'] = 'world'; $this->foo = new SuperArray($array); } public function __get($name){ echo $name.' is being accessed.'.PHP_EOL; return $this->$name; } } $test = new Test; echo $test->foo['bar']['hello'];
Должен выводиться:
foo is being accessed. ['bar'] is being accessed ['bar']['hello'] is being accessed world
Нет, вы не можете. $myTest->foo['bar']['hello'] = 'world';
проходит следующий перевод: $myTest->__get('foo')['bar']['hello'] = 'world';
разбивая их по частям
$tmp = $myTest->__get('foo') $tmp['bar']['hello'] = 'world';
Что вы можете сделать, так это создать производный объект ArrayAccess
. Где вы определяете свой собственный offsetSet()
и возвращаете это из __get()
Вместо возврата массива вы можете вернуть объект, реализующий ArrayAccess . Объекты всегда возвращаются и передаются по ссылке. Это подталкивает проблему, по крайней мере, на уровне вниз.