Bug #52441 [Opn]: Arrays misbehaving with __set() and __get()

2010-11-12 Thread bastard dot internets at gmail dot com
Edit report at http://bugs.php.net/bug.php?id=52441edit=1

 ID: 52441
 User updated by:bastard dot internets at gmail dot com
 Reported by:bastard dot internets at gmail dot com
 Summary:Arrays misbehaving with __set() and __get()
 Status: Open
 Type:   Bug
 Package:Class/Object related
 Operating System:   WIN
 PHP Version:5.3.3 and 5.3.2
 Block user comment: N

 New Comment:

| Could you elaborate your second point? I couldn't understand that
one.



When setting any private property from outside the object, you would
normally expect to get a fatal Cannot access private property error. 
However for private properties that are arrays, the line
$a-test_array[] = 'asdf', where for all intents and purposes you are
modifying a private property, just results in an odd notice.





| Concerning all the other ones: Our sixth point is the solution. This
is expected behavior. To modify an array property it must be returned by
reference. There already have been several bugs on this topic and yet
another one won't change anything ;)



The problem with this solution (__get()) is that get() must always be
defined to return by reference.  And, all other private/protected
properties will have to be returned by reference as well (though I can't
think of where this would be a serious problem off the top of my head).



The manual should at least be updated somewhere to mention that changes
made to private/protected array properties from outside the object are
routed through get(), not set(), and that the get() function must be
defined to return the array property by reference.



Either that or have get() magically return array properties by reference
by default..?


Previous Comments:

[2010-10-03 18:57:49] + at ni-po dot com

Could you elaborate your second point? I couldn't understand that one.



Concerning all the other ones: Our sixth point is the solution. This is
expected behavior. To modify an array property it must be returned by
reference. There already have been several bugs on this topic and yet
another one won't change anything ;)


[2010-07-26 01:50:34] bastard dot internets at gmail dot com

PHP Version: These bugs are found in 5.3.3 and 5.3.2.  Unknown status in
5.2.


[2010-07-26 01:39:17] bastard dot internets at gmail dot com

Der, that last comment was meant to be Amendment to Result #3.  Ignore
that auto-linked reference to bug #3


[2010-07-26 01:36:21] bastard dot internets at gmail dot com

Amendment to bug #3: __set() is bypassed completely, and new arrays can
be freely created within objects if not already protected or private. 
Only if directly setting the array itself (ie $a-test_array =
array();) will __set() be called.  But not when doing something like
a$-test_array[] = 'asdf';


[2010-07-26 01:19:24] bastard dot internets at gmail dot com

Description:

Mixing __set(), __get(), and protected/private/overloaded properties
that are arrays has unexpected, undocumented, and undesirable results. 
A couple of bugs listed below.  One bug is similar to bug 33941, but the
problem still persists and even more bugs have popped up.

Test script:
---
?php

class A {

protected $test_array = array('key' = 'test');

  

function __get($prop) {

if (!property_exists($this, $prop)) {

$this-$prop = null; // just to create it if it didn't 
exist

}

return $this-$prop;

}



function __set($prop, $val) {

$this-$prop = $val;

}

}



$a = new A();

$a-test_array[] = 'asdf';



?

Expected result:

New key/value 0='asdf' assigned to protected class property array
'$test_array'.  If the property didn't yet exist and overloading is
attempted, just create the new '$test_array' property as an array as
intended.  Working with arrays in this manner should work exactly like
with any other variable type.

Actual result:
--
Depending on how the above test script is slightly tweaked, a few bugs
pop up.  The focus here is on what happens with line $a-test_array[] =
'asdf';





1) If $test_array did *not* previously exist, Notice: Indirect
modification of overloaded property A::$test_array has no effect in
...test.php on line 18.  This *should've* worked fine.



2) If __set() was *not* declared, Notice: Indirect modification of
overloaded property A::$test_array has no effect in ...test.php on line
18.  This *should've* resulted in fatal cannot access protected
property error.




Bug #52441 [Opn]: Arrays misbehaving with __set() and __get()

2010-07-25 Thread bastard dot internets at gmail dot com
Edit report at http://bugs.php.net/bug.php?id=52441edit=1

 ID: 52441
 User updated by:bastard dot internets at gmail dot com
 Reported by:bastard dot internets at gmail dot com
 Summary:Arrays misbehaving with __set() and __get()
 Status: Open
 Type:   Bug
 Package:Class/Object related
 Operating System:   WIN
-PHP Version:Irrelevant
+PHP Version:5.3.3 and 5.3.2
 Block user comment: N

 New Comment:

PHP Version: These bugs are found in 5.3.3 and 5.3.2.  Unknown status in
5.2.


Previous Comments:

[2010-07-26 01:39:17] bastard dot internets at gmail dot com

Der, that last comment was meant to be Amendment to Result #3.  Ignore
that auto-linked reference to bug #3


[2010-07-26 01:36:21] bastard dot internets at gmail dot com

Amendment to bug #3: __set() is bypassed completely, and new arrays can
be freely created within objects if not already protected or private. 
Only if directly setting the array itself (ie $a-test_array =
array();) will __set() be called.  But not when doing something like
a$-test_array[] = 'asdf';


[2010-07-26 01:19:24] bastard dot internets at gmail dot com

Description:

Mixing __set(), __get(), and protected/private/overloaded properties
that are arrays has unexpected, undocumented, and undesirable results. 
A couple of bugs listed below.  One bug is similar to bug 33941, but the
problem still persists and even more bugs have popped up.

Test script:
---
?php

class A {

protected $test_array = array('key' = 'test');

  

function __get($prop) {

if (!property_exists($this, $prop)) {

$this-$prop = null; // just to create it if it didn't 
exist

}

return $this-$prop;

}



function __set($prop, $val) {

$this-$prop = $val;

}

}



$a = new A();

$a-test_array[] = 'asdf';



?

Expected result:

New key/value 0='asdf' assigned to protected class property array
'$test_array'.  If the property didn't yet exist and overloading is
attempted, just create the new '$test_array' property as an array as
intended.  Working with arrays in this manner should work exactly like
with any other variable type.

Actual result:
--
Depending on how the above test script is slightly tweaked, a few bugs
pop up.  The focus here is on what happens with line $a-test_array[] =
'asdf';





1) If $test_array did *not* previously exist, Notice: Indirect
modification of overloaded property A::$test_array has no effect in
...test.php on line 18.  This *should've* worked fine.



2) If __set() was *not* declared, Notice: Indirect modification of
overloaded property A::$test_array has no effect in ...test.php on line
18.  This *should've* resulted in fatal cannot access protected
property error.



3) If $test_array did *not* previously exist and __get() was *not*
declared, it will work fine.  __get() *should've* never factored in
here, and $test_array *should've* updated even if already declared
private/protected.



4) If __get() was *not* declared, PHP Fatal error:  Cannot access
protected property A::$test_array.   __get() *should've* never factored
in here.  If the '[]' compound operator is what's causing this, then
__get() should return a copy of the array with new or existing index if
provided to be processed through __set() as expected.



5) If $test_array was public, it will work fine, bypassing __get() and
__set() as intended.  No bug here.



6) If __get() was declared to return a reference to the property (ie
function __get($prop){}), it will work fine and bypass __set().  Not a
bug, but this workaround may cause other problems if expecting to
process updates through __set() or wanting just a copy of any other
property returned by __get().






-- 
Edit this bug report at http://bugs.php.net/bug.php?id=52441edit=1