"Indirect modification of overloaded element of SplFixedArray has no effect" "Indirect modification of overloaded element of SplFixedArray has no effect" arrays arrays

"Indirect modification of overloaded element of SplFixedArray has no effect"


First, the problem is related to all classes which implement ArrayAccess it is not a special problem of SplFixedArray only.


When you accessing elements from SplFixedArray using the [] operator it behaves not exactly like an array. Internally it's offsetGet() method is called, and will return in your case an array - but not a reference to that array. This means all modifications you make on $a[0] will get lost unless you save it back:

Workaround:

$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);

Here is an example using a scalar which fails too - just to show you that it is not related to array elements only.


This is actually fixable if you slap a & in front of offsetGet (assuming you have access to the internals of your ArrayAccess implementation):

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)]);    }}


Adding my experience with the same error, in case it helps anyone:

I recently imported my code into a framework with a low error-tolerance (Laravel). As a result, my code now throws an exception when I try to retrieve a value from an associative array using a non-existent key. In order to deal with this I tried to implement my own dictionary using the ArrayAccess interface. This works fine, but the following syntax fails:

$myDict = new Dictionary();$myDict[] = 123;$myDict[] = 456;

And in the case of a multimap:

$properties = new Dictionary();$properties['colours'] = new Dictionary();$properties['colours'][] = 'red';$properties['colours'][] = 'blue';

I managed to fix the problem with the following implementation:

<?phpuse ArrayAccess;/** * Class Dictionary * * DOES NOT THROW EXCEPTIONS, RETURNS NULL IF KEY IS EMPTY * * @package fnxProdCrawler */class Dictionary implements ArrayAccess{    // FOR MORE INFO SEE: http://alanstorm.com/php_array_access    protected $dict;    function __construct()    {        $this->dict = [];    }    // INTERFACE IMPLEMENTATION - ArrayAccess    public function offsetExists($key)    {        return array_key_exists($key, $this->dict);    }    public function offsetGet($key)    {        if ($this->offsetExists($key))            return $this->dict[$key];        else            return null;    }    public function offsetSet($key, $value)    {        // NOTE: THIS IS THE FIX FOR THE ISSUE "Indirect modification of overloaded element of SplFixedArray has no effect"        // NOTE: WHEN APPENDING AN ARRAY (E.G. myArr[] = 5) THE KEY IS NULL, SO WE TEST FOR THIS CONDITION BELOW, AND VOILA        if (is_null($key))        {            $this->dict[] = $value;        }        else        {            $this->dict[$key] = $value;        }    }    public function offsetUnset($key)    {        unset($this->dict[$key]);    }}

Hope it helps.