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

时间:2018-08-05 20:14:12

标签: php isset arrayaccess

我编写了实现ArrayAccess接口的简单PHP类:

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 bug 62059有关。

该代码适用于3V4L,因此您可以查看出了什么问题。我添加了一些其他的调试调用,如果未定义index,则引发异常,因为在3V4L中未显示通知: https://3v4l.org/7C2Fs

应该没有任何通知,否则PHPUnit测试将失败。 如何解决此错误?

2 个答案:

答案 0 :(得分:0)

这似乎是旧版本的PHP和HHVM中的一个PHP错误。由于不再支持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;
    }
}

请参见3V4Lzerkms的注释处的代码(firstsecondthird)。

答案 1 :(得分:-1)

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

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

代替:

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