PHP 5.6:ArrayAccess:函数isset调用offsetGet导致未定义索引通知

PHP 5.6: ArrayAccess: Function isset calls offsetGet and causes undefined index notice

我写了简单的 PHP class 实现了 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;
    }
}

在PHP7中正常,在PHP5.6和HHVM中出现问题

如果我在未定义的索引上调用函数 isset(),PHP 将调用 offsetGet() 而不是 offsetExists(),这将引起 Undefined index 通知。

在PHP7中,只有offsetExists()returnstrue才调用offsetGet(),所以不会报错。

我认为这与 PHP bug 62059 有关。

代码在3V4L可用,所以你可以看看哪里错了。如果索引未定义,我又添加了几个调试调用并抛出异常,因为通知未在 3V4L 中显示: https://3v4l.org/7C2Fs

不应该有任何通知,否则PHP单元测试将失败。 我该如何解决这个错误?

我不确定我是否理解你的问题,但也许你可以试试

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

而不是:

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

看起来这是旧版本 PHP 和 HHVM 中的一个 PHP 错误。因为PHP 5.6 不再被支持,这个错误将不会被修复。

快速修复是添加额外的签入方法 offsetGet() 和 return 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 and zerkms's comments (, , 处的代码)。