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 не пройдут. Как я могу исправить эту ошибку?


person Filip Š    schedule 05.08.2018    source источник
comment
Это похоже на ошибку php. В качестве быстрого и грязного исправления вы можете дополнительно запустить проверку в offsetSet.   -  person zerkms    schedule 05.08.2018
comment
Что я могу сделать? Есть какое-то временное решение? Как я могу пройти тест PHPUnit?   -  person Filip Š    schedule 05.08.2018
comment
Вы можете использовать isset, чтобы проверить, существует ли ключ, прежде чем обращаться к нему.   -  person zerkms    schedule 05.08.2018
comment
Если это ошибка PHP и HHVM, куда я могу сообщить об этом?   -  person Filip Š    schedule 05.08.2018
comment
На bugs.php.net вы сообщаете об ошибках php, но 5.6 все равно не будет исправлена ​​- она ​​не поддерживается больше. И вообще разработан ли HHVM?   -  person zerkms    schedule 05.08.2018
comment
Да, проверил и изменил свой комментарий, извините   -  person zerkms    schedule 05.08.2018
comment
Таким образом, единственное решение — добавить проверку в offsetGet?   -  person Filip Š    schedule 05.08.2018
comment
Я так думаю - если php вызывает этот метод, у вас нет другого выбора.   -  person zerkms    schedule 05.08.2018


Ответы (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 (сначала, секунда, третий).

person Filip Š    schedule 06.08.2018

Я не уверен, что понял ваш вопрос, но, может быть, вы могли бы попробовать

public function __construct($value =[]){
    $this->value = $value;
}

вместо:

public function __construct($value = null){
$this->value = $value;
}
person M.Brian    schedule 05.08.2018
comment
Вы не понимаете мой вопрос. Проблема в том, что старые версии PHP и HHVM вызывают неверный метод, что приводит к ошибке. - person Filip Š; 05.08.2018