Bug #52861 [Com]: unset failes with ArrayObject and deep arrays

2011-11-18 Thread nemo at ikkoku dot de
Edit report at https://bugs.php.net/bug.php?id=52861edit=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]=
   

Bug #52861 [Com]: unset failes with ArrayObject and deep arrays

2011-01-07 Thread auke at muze dot nl
Edit report at http://bugs.php.net/bug.php?id=52861edit=1

 ID: 52861
 Comment by: auke at muze dot nl
 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:

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.


Previous Comments:

[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 http://bugs.php.net/bug.php?id=52861edit=1


Bug #52861 [Com]: unset failes with ArrayObject and deep arrays

2011-01-07 Thread auke at muze dot nl
Edit report at http://bugs.php.net/bug.php?id=52861edit=1

 ID: 52861
 Comment by: auke at muze dot nl
 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:

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 :)


Previous Comments:

[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 http://bugs.php.net/bug.php?id=52861edit=1


Bug #52861 [Com]: unset failes with ArrayObject and deep arrays

2011-01-05 Thread auke at muze dot nl
Edit report at http://bugs.php.net/bug.php?id=52861edit=1

 ID: 52861
 Comment by: auke at muze dot nl
 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:

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)

}


Previous Comments:

[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 http://bugs.php.net/bug.php?id=52861edit=1