“间接修改SplFixedArray的过载元素没有效果”

2022-08-30 15:38:26

为什么会出现以下情况

$a = new SplFixedArray(5);
$a[0] = array(1, 2, 3);
$a[0][0] = 12345; // here
var_dump($a);

生产

Notice: Indirect modification of overloaded element of SplFixedArray has no effect in <file> on line <indicated>

这是一个错误吗?那么,您如何处理多维 SplFixedArrays 呢?有什么解决方法吗?


答案 1

首先,这个问题与实现它的所有类有关,这不仅仅是一个特殊问题。ArrayAccessSplFixedArray


当您使用运算符访问元素时,它的行为与数组不完全相同。在内部调用它的方法,并在您的案例中返回一个数组 - 但不是对该数组的引用。这意味着您所做的所有修改都将丢失,除非您将其保存回去:SplFixedArray[]offsetGet()$a[0]

解决方法:

$a = new SplFixedArray(5);
$a[0] = array(1, 2, 3); 
// get element
$element = $a[0];
// modify it
$element[0] = 12345;
// store the element again
$a[0] = $element;

var_dump($a);

这是一个使用标量的例子,它也失败了 - 只是为了向你表明它不仅仅与数组元素相关。


答案 2

如果你在前面打一个,这实际上是可以修复的(假设你可以访问你的实现的内部):&offsetGetArrayAccess

class Dict implements IDict {
    private $_data = [];

    /**
     * @param mixed $offset
     * @return bool
     */
    public function offsetExists($offset) {
        return array_key_exists(self::hash($offset), $this->_data);
    }

    /**
     * @param mixed $offset
     * @return mixed
     */
    public function &offsetGet($offset) {
        return $this->_data[self::hash($offset)];
    }

    /**
     * @param mixed $var
     * @return string
     */
    private static function hash($var) {
        return is_object($var) ? spl_object_hash($var) : json_encode($var,JSON_UNESCAPED_SLASHES);
    }

    /**
     * @param mixed $offset
     * @param mixed $value
     */
    public function offsetSet($offset, $value) {
        $this->_data[self::hash($offset)] = $value;
    }

    /**
     * @param mixed $offset
     */
    public function offsetUnset($offset) {
        unset($this->_data[self::hash($offset)]);
    }
}