ID: 41641
Comment by: cscott at ggot dot org
Reported By: asnyder at mddev dot com
Status: No Feedback
Bug Type: Scripting Engine problem
Operating System: Linux Fedora Core 4
PHP Version: 5.2.3
Assigned To: helly
New Comment:
First, a much simpler test case:
class foo {
private $bar = array();
public function __construct() {
$this->bar[0] = new stdClass;
$this->bar[0]->five = 5;
}
public function __get($n) {
return $this->bar;
}
}
$foo = new foo;
$foo->bar[0]->seventeen = 17;
var_dump($foo);
* * *
Of course, this produces:
object(foo)#1 (1) {
["bar":"foo":private]=>
array(1) {
[0]=>
object(stdClass)#2 (2) {
["five"]=>
int(5)
["seventeen"]=>
int(17)
}
}
}
But also generates the warning. The warning is certainly useful for
informing users that they are not actually modifying the array index
inside the class when using non-objects, but since all objects are
considered to be passed by reference this warning is indeed quite
bogus, and breaks formatted responses (e.g. from a web service).
Furthermore, using a by-reference declaration for __get is a horse of
a different color, as I am passing entire properties by reference, and
if I'm going to do that I might as well just make them public to begin
with and circumvent the performance hit incurred with __get. However,
there is a reason these properties are private with __get pseudo-
access, so either of these solutions is less than ideal.
Simply put, this notice only occurs when an array index fetched via
__get is used in conjunction with some type of assignment, so would it
be so difficult to check, before generating this notice, whether the
value at that array index is, in fact, a reference?
Fun side node, if you nest objects you can get multiple notices.
Assuming the class declaration from above:
$foo = new foo;
$foo->bar[0]->baz = new foo; // generates one notice
$foo->bar[0]->baz->bar[0]->eleven = 11; // generates two notices
That code will generate 3 notices altogether, and yet the object
structure will look *exactly* how one would expect it to look.
Ironically, one could circumvent all of this by using an object
instead of an array -- except that objects don't support numerical
member names, or even access without some massaging, which can even
end you up back in square one with nothing but wasted time to show for
it.
Previous Comments:
------------------------------------------------------------------------
[2008-11-10 01:00:03] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
------------------------------------------------------------------------
[2008-11-02 13:11:35] [email protected]
Please try using this CVS snapshot:
http://snaps.php.net/php5.2-latest.tar.gz
For Windows:
http://windows.php.net/snapshots/
------------------------------------------------------------------------
[2007-11-25 20:46:22] g42 at gmx dot net
brjann:
well, you're right, it will work if you use "public function
&__get(){...}". But that solution will not call __set at all (which is a
problem in some cases).
the following example won't throw a warning and will basically work:
<?php
error_reporting(E_ALL);
class newclass {
private $properties;
public function &__get($key) {
echo "get $key<br>";
return $this->properties[$key];
}
public function __set($key, $val) {
echo "set $key to $val<br>";
$this->properties[$key] = $val;
}
}
$c = new newclass;
$c->array['test'] = 'test';
?>
expected output:
get array
set array to test
actual output:
get array
I understand that it's not possible to catch this modification because
it's done via reference, so i won't write a bugreport... Although it's
still a bit confusing...
------------------------------------------------------------------------
[2007-09-27 20:16:19] brjann at gmail dot com
It seems that declaring the getter as "public function &__get(){...}"
does the trick. However, it took some googling to find.
------------------------------------------------------------------------
[2007-09-25 16:22:55] brjann at gmail dot com
When 5.2.0 was released, several complaints about this issue were
submitted (see http://bugs.php.net/bug.php?id=39449), and it was
resolved. But now we're there again.
Fact is that this seriously breaks wrapping functions that my project
relies on, and I still don't understand the logic of modification of
overloaded array properties not working is expected behaviour, while
modification of non-array properties works.
Will this be fixed? If not, why, and why was it then fixed after bug
report 39449? Was it just so that me and others would keep on writing
code that is now useless?
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/41641
--
Edit this bug report at http://bugs.php.net/?id=41641&edit=1