PHP 5.6: ArrayAccess: функция isset вызывает offsetGet и вызывает неопределенное уведомление об индексе
Я написал простой класс PHP, который реализует интерфейс ArrayAccess:
class MyArray implements ArrayAccess
{
public $value;
public function __construct($value = null)
{
$this->value = $value;
}
public function &offsetGet($offset)
{
var_dump(__METHOD__);
if (!isset($this->value[$offset])) {
throw new Exception('Undefined index: ' . $offset);
}
return $this->value[$offset];
}
public function offsetExists($offset)
{
var_dump(__METHOD__);
return isset($this->value[$offset]);
}
public function offsetSet($offset, $value)
{
var_dump(__METHOD__);
$this->value[$offset] = $value;
}
public function offsetUnset($offset)
{
var_dump(__METHOD__);
$this->value[$offset] = null;
}
}
Он работает нормально в PHP 7, но проблема в PHP 5.6 и HHVM.
Если я вызываю функцию isset()
по неопределенному индексу PHP вызовет offsetGet()
вместо offsetExists()
что приведет к Undefined index
уведомление.
В PHP 7 это вызывает offsetGet()
только если offsetExists()
возвращается true
, так что ошибки нет.
Я думаю, что это связано с ошибкой PHP 62059.
Код доступен в 3V4L, так что вы можете увидеть, что не так. Я добавил еще несколько вызовов отладки и выбросил исключение, если индекс не определен, потому что уведомления не отображаются в 3V4L: https://3v4l.org/7C2Fs
Не должно быть никакого уведомления, иначе тесты PHPUnit не пройдут. Как я могу исправить эту ошибку?
2 ответа
Похоже, что это ошибка PHP в старых версиях PHP и HHVM. Поскольку PHP 5.6 больше не поддерживается, эта ошибка не будет исправлена.
Быстрое решение состоит в том, чтобы добавить дополнительную проверку в методе offsetGet()
и вернуться null
если индекс не определен:
class MyArray implements ArrayAccess
{
public $value;
public function __construct($value = null)
{
$this->value = $value;
}
public function &offsetGet($offset)
{
if (!isset($this->value[$offset])) {
$this->value[$offset] = null;
}
return $this->value[$offset];
}
public function offsetExists($offset)
{
return isset($this->value[$offset]);
}
public function offsetSet($offset, $value)
{
$this->value[$offset] = $value;
}
public function offsetUnset($offset)
{
$this->value[$offset] = null;
}
}
Смотрите код в 3V4L и комментарии zerkms( первый, второй, третий).
Я не уверен, что понял ваш вопрос, но, возможно, вы могли бы попробовать
public function __construct($value =[]){
$this->value = $value;
}
вместо:
public function __construct($value = null){
$this->value = $value;
}