Первоначально я думал, что это будет кусок пирога .. не для меня ..
Я пытаюсь расширить функцию offsetGet (), чтобы она возвращала ноль, если элемент отсутствует в ArrayObject. Пока я не могу заставить его работать без ошибок.
php -v: 5.3.29
Что я делаю неправильно? Ниже мой код и ошибка:
Мой расширенный класс ArrayObject:
class IssetArray extends \ArrayObject {
public function &offsetGet($offset) {
$var = $this->offsetExists($offset) ? parent::offsetGet($offset) : null;
return $var;
}
}
Вот как я это называю:
$array = new \IssetArray();
$array['item'] = 123;
var_dump($array['item']);
var_dump($array['something']['noItem']);
$array['something']['foo'] = 'bar';
var_dump($array['something']['foo']);
$normalArrayObject = new \ArrayObject();
$normalArrayObject['something']['foo'] = 'bar';
var_dump($normalArrayObject['something']['foo']);
var_dump($normalArrayObject['something']['noItem']);
Выходы:
int(123)
NULL
Notice: Indirect modification of overloaded element of \IssetArray has no effect in -- on line --
NULL
string(3) "bar"Notice: Undefined index: noItem in -- on line --
NULL
Что я делаю неправильно?? Если я вызываю обычный ArrayObject, я не получаю косвенную ошибку модификации. Я в таком замешательстве.
Любая помощь будет замечательной. Я гуглил и гуглил без удачи.
Обновить
————
При попытке сделать то же самое с ArrayAccess я сталкиваюсь с той же проблемой. Как я могу обойти это с ArrayAccess?
Моя реализация:
class IssetArray implements \ArrayAccess {
private $container = array();
public function __construct() {}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function &offsetGet($offset) {
$var = isset($this->container[$offset]) ? $this->container[$offset] : null;
return $var;
}
}
Это приводит к той же самой проблеме, которую я вижу с ArrayObject. Примечание: косвенное изменение перегруженного элемента \ IssetArray не оказывает никакого влияния на
Короткий ответ: это неприятный побочный эффект перегрузки offsetGet()
метод из ArrayObject
,
$array['something']['foo'] = 'bar';
Как часть задания, ArrayObject::offsetGet('something')
вызывается и ожидается, что возвращаемое значение вернет ссылку; проблема в том, что, несмотря на определение &offsetGet()
, это на самом деле не возвращает ссылку.
Что ты есть действительно возвращение является временной переменной, и, следовательно, уведомление является правильным, чтобы утверждать, что любые изменения, внесенные в эту переменную, не будут отражены в окончательном массиве.
Кстати, это не произойдет, если вы реализуете ArrayAccess
вместо; конечно, вы не получите все методы, которые идут с ArrayObject
или 🙁
Кажется из этот отчет что HHVM демонстрирует правильное поведение, а PHP 7 не будет генерировать никаких уведомлений (но имеет неправильное поведение во время назначения).
Мне удалось заставить приведенную ниже реализацию ArrayAccess работать идеально для моих нужд. Надеюсь, это поможет всем, у кого проблемы такого же типа, как у меня.
Спасибо @Jack за помощь в правильном направлении!
class IssetArray implements \ArrayAccess {
private $container = array();
public function __construct() {}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function &offsetGet($offset) {
if(!isset($this->container[$offset])) {
$this->container[$offset] = null;
}
return $this->container[$offset];
}
}