"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.