EDIT: Я понял, что количество текста может быть пугающим. Суть этого вопроса:
Как реализовать ArrayAccess таким образом, чтобы можно было установить многомерные значения?PHP ArrayAccess set multimensional
Я знаю, что это обсуждалось уже here но мне кажется, не в состоянии правильно реализовать интерфейс ArrayAccess.
В принципе, у меня есть класс для обработки конфигурации приложения с помощью массива и реализовано ArrayAccess
. Получение значений отлично работает, даже значения из вложенных ключей ($port = $config['app']['port'];
). Установка значений работает только для одномерных массивов, но: Как только я пытаюсь (ип) установить значение (., Например, порт в предыдущем примере), я получаю следующее сообщение об ошибке:
Notice: Indirect modification of overloaded element <object name> has no effect in <file> on <line>
сейчас общее мнение, по-видимому, заключается в том, что метод offsetGet()
должен возвращаться по ссылке (&offsetGet()
). Это, однако, не решает проблему, и я боюсь, что не знаю, как правильно реализовать этот метод - почему метод getter используется для установки значения? Php doc here тоже не очень полезен.
Чтобы непосредственно повторить это (PHP 5,4-5,6), пожалуйста, найти пример кода прилагается ниже:
<?php
class Config implements \ArrayAccess
{
private $data = array();
public function __construct($data)
{
$this->data = $data;
}
/**
* ArrayAccess Interface
*
*/
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}
public function &offsetGet($offset)
{
return isset($this->data[$offset]) ? $this->data[$offset] : null;
}
public function offsetExists($offset)
{
return isset($this->data[$offset]);
}
public function offsetUnset($offset)
{
unset($this->data[$offset]);
}
}
$conf = new Config(array('a' => 'foo', 'b' => 'bar', 'c' => array('sub' => 'baz')));
$conf['c']['sub'] = 'notbaz';
EDIT 2: Решение , как отметил Райан, должен был использовать ArrayObject (который уже реализует ArrayAccess
, Countable
и IteratorAggregate
).
Чтобы применить его к классу держа массив, структура его следующим образом:
<?php
class Config extends \ArrayObject
{
private $data = array();
public function __construct($data)
{
$this->data = $data;
parent::__construct($this->data);
}
/**
* Iterator Interface
*
*/
public function getIterator() {
return new \ArrayIterator($this->data);
}
/**
* Count Interface
*
*/
public function count()
{
return count($this->data);
}
}
Я использовал это для моей библиотеки Config libconfig
, которая доступна на Github под лицензией MIT.
Эй, спасибо большое! Мне пришлось реализовать функцию 'getIterator', но это было легко (обновил вопрос). Спасибо! :) –