php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39337 Array creation when using overloading (__get) does not work (NULL)
Submitted: 2006-11-01 18:41 UTC Modified: 2007-01-17 21:47 UTC
Votes:1
Avg. Score:2.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: phpbugs at thequod dot de Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 5CVS-2006-11-01 (CVS) OS: Ubuntu Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: phpbugs at thequod dot de
New email:
PHP Version: OS:

 

 [2006-11-01 18:41 UTC] phpbugs at thequod dot de
Description:
------------
Creating an array through $obj->a[] or $obj->a[$index] 
does not create an array, if you use overloading through 
the "__get()" method.

This happens with PHP_5_2 and 5.1.6 from Ubuntu, which 
I've also tested.

The workaround seems to be to initialize the member 
explicitly to "array()".

Reproduce code:
---------------
<?php

class A
{
	function __get($v)
	{
		// note: even returning array() here won't fix it  
	}
}


$A = new A();

$A->foo[1] = 1;
var_dump( $A->foo );

$A->foo[] = 2;
var_dump( $A->foo );

$A->foo['a'] = 3;
var_dump( $A->foo );

$A->foo = array();
var_dump( $A->foo );

$A->foo = 1;
var_dump( $A->foo );

?>

Expected result:
----------------
array(1) {
  [1]=>
  int(1)
}
array(2) {
  [1]=>
  int(1)
  [2]=>
  int(2)
}
array(3) {
  [1]=>
  int(1)
  [2]=>
  int(2)
  ["a"]=>
  int(3)
}
array(0) {
}
int(1)


Actual result:
--------------
NULL
NULL
NULL
array(0) {
}
int(1)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-11-01 18:56 UTC] phpbugs at thequod dot de
A better workaround is, of course, to just define the 
member with "var" in the class header.

But it's still a bug IMHO.
 [2006-11-08 14:10 UTC] tony2001@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php


 [2006-11-08 17:30 UTC] phpbugs at thequod dot de
Sorry, it's not in the manual..

http://de.php.net/manual/en/language.oop5.overloading.php

Please re-classify as "documentation issue" at least, if you're sure that it really is not a bug..
 [2006-11-08 17:40 UTC] tony2001@php.net
It's not in the manual, because it's obvious - your __get() method does nothing, so you get nothing as the result.
 [2006-11-08 23:18 UTC] phpbugs at thequod dot de
Ok. But haven't you seen the comment in __get()?

Here's another testcase, just returning an array now 
always and with further output, when __get() gets called:


Description:
------------
When using "array creating syntax" (like $a[] or $a[1]), 
__get() does not seem to work correctly, IF the var has 
not been defined using the "var" key for the class.

Reproduce code:
---------------
<?php

class A
{
        function __get($v)
        {
                // note: even returning array() here won't 
fix it  
        }
}


$A = new A();

$A->foo[1] = 1;
var_dump( $A->foo );

$A->foo[] = 2;
var_dump( $A->foo );

$A->foo['a'] = 3;
var_dump( $A->foo );

$A->foo = array();
var_dump( $A->foo );

$A->foo = 1;
var_dump( $A->foo );

?>

Expected result:
----------------
__get: foo
array(1) {
  1 => 1
}
array(2) {
  1 => 1,
  2 => 2
}
array(0) {
  1 => 1,
  2 => 2,
  'a' => 3
}
array(0) {
}
int(1)


Actual result:
--------------
__get: foo
__get: foo
array(0) {
}
__get: foo
__get: foo
array(0) {
}
__get: foo
__get: foo
array(0) {
}
array(0) {
}
int(1)
 [2006-11-08 23:47 UTC] tony2001@php.net
Yes, I did see the comment. 
The point is that with $A->foo[] = 1; you call __get() first, which returns NULL and you modify this temporary variable. That happens because we need to get the array itself to be able to add an element, but to create a variable directly (like $A->foo = 1) this is not needed.

 [2006-11-09 00:22 UTC] phpbugs at thequod dot de
Sorry, to reopen it again.

The "Reproduce code" in the comment above was wrong.

I've let it return "array()" always and this changes the 
output, so that it is "array()" instead of "NULL".

But still: the array does not get changed!

I've written a comment for Bug 39426, which seems to 
suffer from something related, but cannot post it, because 
it's bogus.. :/
 [2006-11-09 00:30 UTC] tony2001@php.net
I've already explained everything, just read my previous comment carefully.
 [2006-11-09 18:41 UTC] phpbugs at thequod dot de
Ok. I've even slept over it.

Why should this not work?

---------------------------------
<?php
class A
{
        function __get($v)
        {
                if( isset($this->var) )
                        return $this->var;
                return array();
        }
}


$A = new A();

$A->foo[] = 1;
var_dump( $A->foo );
?>
---------------------------------

It prints:
array(0) {
}

Your comment, which I've reread carefully, does not 
explain it. The temp var from __get() is first array and 
later the $var itself.

Adding a __set() method to the class shows that this does 
not get called at all.
 [2006-11-09 19:01 UTC] phpbugs at thequod dot de
Re: I've also said it before.. it works, if the var is set 
in the constructor. To see the diff:

------------------------------------
<?php
class A
{
        private $vars;
        function __get($v)
        {
                if( isset($this->vars[$v]) )
                        return $this->vars[$v];
                return array();
        }

        function __set($v, $vv)
        {
                echo "__set: '$v'\n";
                var_dump($vv);
                $this->vars[$v] = $vv;
        }
}

class B extends A
{
        var $foo;
}


$A = new A();
$B = new B();

echo "A: ----------------\n";
$A->foo[] = 1;
var_dump( $A->foo );

echo "B: ----------------\n";
$B->foo[] = 1;
var_dump( $B->foo );
?>
-----------------------------------

Result:
-------
A: ----------------
array(0) {
}
B: ----------------
array(1) {
  [0]=>
  int(1)
}
 [2007-01-07 04:10 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Notice: Indirect modification of overloaded property A::$foo 
has no effect.

This is why the assignment has no effect.
 [2007-01-07 19:31 UTC] phpbugs at thequod dot de
iliaa, thanks for taking the time to look at this.

Unfortunately I don't understand your note. A::$foo is 
overloaded in class B and there it shows the IMHO correct 
behaviour (because in class B there's "var $foo").

The expected result in the last code example would have 
been:
A: ----------------
array(1) {
  [0]=>
  int(1)
}
B: ----------------
array(1) {
  [0]=>
  int(1)
}

instead of:

A: ----------------
array(0) {
}
B: ----------------
array(1) {
  [0]=>
  int(1)
}
 [2007-01-07 21:57 UTC] iliaa@php.net
foo property is not actually created, hence the warning.
 [2007-01-14 05:26 UTC] phpbugs at thequod dot de
ilia, which warning are you talking about? There's no 
(PHP) warning?!

All I want to say is: overloading of arrays by 
e.g. "$Foo->bar[] = 1" does not work, if $bar is not 
defined as a member in the class definition (without a 
value, of course).
 [2007-01-17 21:02 UTC] tony2001@php.net
Ilia is talking about this warning:
Notice: Indirect modification of overloaded property A::$foo has no effect
 [2007-01-17 21:47 UTC] phpbugs at thequod dot de
I cannot believe that I've not seen the Notice before, but 
now I do. Sorry.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 13:01:28 2024 UTC