Edit report at https://bugs.php.net/bug.php?id=52861&edit=1
ID: 52861 Comment by: nemo at ikkoku dot de Reported by: mep_eisen at web dot de Summary: unset failes with ArrayObject and deep arrays Status: Open Type: Bug Package: SPL related Operating System: Windows Vista 64 PHP Version: 5.3.3 Block user comment: N Private report: N New Comment: One can still use unset if one writes: ----------- >8 ----------- $a = ArrayObject(Array('foo' => Array('bar' => 1))); // Won't work ($a['foo']['bar'] is still 1) // Also a notice is displayed: PHP Notice: Indirect modification of // overloaded element of ArrayObject has no effect in php shell code on line ... var_dump($a); unset($a['foo']['bar']); var_dump($a); // This works var_dump($a); $v =& $a['foo']; unset($v['bar']); var_dump($a); // This also works //$v =& $a['foo']['bar']; //unset($v); ----------- 8< ----------- Previous Comments: ------------------------------------------------------------------------ [2011-01-07 12:37:52] auke at muze dot nl Just checked with php 5.3.3 and there the code runs as expected, so at least setting works with a nested array. For the record I tried the original bugreport code as well and got the same result, on a linux system, 64 bits (debian), but also this notice: PHP Notice: Indirect modification of overloaded element of ArrayObject has no effect in /var/www/test/test.php on line 22 So at least PHP is honest in that it doesn't work :) ------------------------------------------------------------------------ [2011-01-07 12:07:34] auke at muze dot nl I found a workaround for the problem that suddenly the parent object has any property you try to access and has it filled with the previously set array. If the containing object has its own __get() method which always returns NULL, the object is safe again. So this code works as expected: class IWouldLikeToPointOutABug { function __get( $name ) { return NULL; } } $buggy = new IWouldLikeToPointOutABug(); $buggy->bug = new ArrayObject( ); $buggy->bug['foo']['bar'] = true; echo "This looks normal\r\n"; var_dump( $buggy ); echo "This should be NULL\r\n"; var_dump( $buggy->thisIsNotHere ); One drawback is that you cannot assign properties by reference anymore because you're now using the __get() overloading method. This does not fix the original bug where unsetting fails. BTW. Our original workaround involved creating our own arrayobject by implementing all the array interfaces, but that will not work either. When you do this: $arrayobject['unsetkey']['key'] = $value; The offsetSet method is never called for 'unsetKey', just the offsetGet. So there is no way to implement the correct behaviour. ------------------------------------------------------------------------ [2011-01-05 18:51:51] auke at muze dot nl It's worse than this, ArrayObject gets confused on where to put the data and mangles any containing object: test script: class IWouldLikeToPointOutABug { } $buggy = new IWouldLikeToPointOutABug(); $buggy->bug = new ArrayObject( ); $buggy->bug['foo']['bar'] = true; echo "This looks normal\r\n"; var_dump( $buggy ); echo "This should be NULL\r\n"; var_dump( $buggy->thisIsNotHere ); Results in: This looks normal object(IWouldLikeToPointOutABug)#1 (1) { ["bug"]=> object(ArrayObject)#2 (0) { } } This should be NULL array(1) { ["bar"]=> bool(true) } ------------------------------------------------------------------------ [2010-09-16 17:23:11] mep_eisen at web dot de Description: ------------ Using deep arrays unset itself or ArrayObject misbehaves. It silently does nothing. The problem lies in iteration 3 that mixes ArrayObject and classic arrays. Test script: --------------- echo "iteration1\n"; $arr = new ArrayObject(); $arr['foo'] = new ArrayObject(); $arr['foo']['bar'] = true; unset($arr['foo']['bar']); var_dump($arr); echo "iteration2\n"; $arr = array(); $arr['foo']['bar'] = true; unset($arr['foo']['bar']); var_dump($arr); echo "iteration3\n"; $arr = new ArrayObject(); $arr['foo']['bar'] = true; unset($arr['foo']['bar']); var_dump($arr); Expected result: ---------------- iteration1 object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> array(1) { ["foo"]=> object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> array(0) { } } } } iteration2 array(1) { ["foo"]=> array(0) { } } iteration3 object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> array(1) { ["foo"]=> array(0) { } } } Actual result: -------------- iteration1 object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> array(1) { ["foo"]=> object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> array(0) { } } } } iteration2 array(1) { ["foo"]=> array(0) { } } iteration3 object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> array(1) { ["foo"]=> array(1) { ["bar"]=> bool(true) } } } ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=52861&edit=1