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

Reply via email to