php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39449 Overloaded array properties do not work correctly
Submitted: 2006-11-09 13:43 UTC Modified: 2008-07-21 17:48 UTC
Votes:78
Avg. Score:4.7 ± 0.7
Reproduced:75 of 75 (100.0%)
Same Version:46 (61.3%)
Same OS:32 (42.7%)
From: pstradomski at gmail dot com Assigned: dmitry (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.2.0 OS: Linux
Private report: No CVE-ID: None
 [2006-11-09 13:43 UTC] pstradomski at gmail dot com
Description:
------------
It is now impossible to implement overloaded array properties. Array returned via __get is now a copy (not a reference as in 5.1.x) and it is impossible to force getter to pass a reference.

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

class A {
public function & __get($val) {
  return $this->keys[$val];
}
public function __set($k, $v) {
  $this->keys[$k] = $v;
}
private $keys = array();
}

$a =new A();

$a->arr = array('a','b','c');

$b = &$a->arr;
$b[]= 'd';

foreach ($a->arr as $k => $v) {
  echo "$k => $v\n";
}

$a->arr[]='d';

foreach ($a->arr as $k => $v) {
  echo "$k => $v\n";
}

?>

Expected result:
----------------
0 => a
1 => b
2 => c
3 => d

0 => a
1 => b
2 => c
3 => d
4 => d


Actual result:
--------------
Notice: Indirect modification of overloaded property A::$arr has no effect in /home/pawel/tmp/a.php on line 18

Notice: Indirect modification of overloaded property A::$arr has no effect in /home/pawel/tmp/a.php on line 21
0 => a
1 => b
2 => c

Notice: Indirect modification of overloaded property A::$arr has no effect in /home/pawel/tmp/a.php on line 25

Notice: Indirect modification of overloaded property A::$arr has no effect in /home/pawel/tmp/a.php on line 27
0 => a
1 => b
2 => c


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-11-09 13:50 UTC] tony2001@php.net
This is expected behaviour.
 [2006-11-09 14:05 UTC] pstradomski at gmail dot com
Reopening.

This should never be "expected behaviour". This way encapsulation got severly broken - __get was introduced to allow dynamic creation of properties - and therefore implementation of record-like classes. Such properties were meant to be indistinguishable from standard properties - but aren't. Neither passing by reference works, nor array elements do.

Developer can expect to be able to modify object properties for example in such a way:

$x->arr = array('a');
array_push($x->arr, 'b');

Now it is impossible - although it should be. I understand previous behaviour could be considered improper, bu now developers don't even get a chance to choose between passing by value and passing by reference.
 [2006-11-14 20:31 UTC] cboden at gmail dot com
In the above example:
  $a->arr[]='d';
produced the expected results in PHP-5.1 but now gives the following error in PHP-5.2
"Notice: Indirect modification of overloaded property"
 [2006-11-19 11:53 UTC] v dot anagnostos at mail dot bg
Reproduce code:
---------------

<?php

class A{
	
	private $test = array(1,2,3,4,5);
		
	public function __get($v){
		return $this->test;
	}

}

$a = new A;

foreach( $a->overloaded_property as $val )
	echo $val."<br />\n";

?>

Expected result:
----------------

1
2
3
4
5

Actual result:
--------------

Notice: Indirect modification of overloaded property A::$overloaded_property has no effect in C:\Apache\htdocs\dancho\index.php on line 15
1
2
3
4
5
 [2006-12-04 08:55 UTC] denis at edistar dot com
I think the warning should be raised only when someone is 
trying to write the overloaded property.

Foreach and other loop constructs are readonly constructs 
except when they are using references of the overloaded 
properties.

For example:
<?php

class A{
        
        private $test = array(1,2,3,4,5);
                
        public function __get($v){
                return $this->test;
        }

}

$a = new A;

// This should not raise notice
foreach( $a->overloaded_property as $val )
        echo $val."<br />\n";

// This should raise notice
$a->overloaded_property[] = 6;

?>

Thank you,
Denis
 [2006-12-06 11:08 UTC] brjann at gmail dot com
"// This should not raise notice
foreach( $a->overloaded_property as $val )
        echo $val."<br />\n";

// This should raise notice
$a->overloaded_property[] = 6;"

I do not agree with that. Neither of the examples should raise a notice. There is no reason for

$a->overloadedprop = $bar

to work, but not

$a->overloadedprop[$foo] = $bar 

or

foreach($a->overloadedprop){}

Either properties can be overloaded and therefore read, assigned and iterated over, or not. Overloaded properties should behave the same way as ordinary properties, or else the object's behaviour is unpredictable.

Perhaps the solution of using __get() to return a reference is unsatisfactory in some way, but the behaviour should still be there.

/Brj?nn
 [2006-12-06 22:18 UTC] mail at peter-thomassen dot de
I do agree with Denis in the sense that one should disable 
the notice for read access (using foreach, p.ex.), until a 
global solution including write access is found (or not). 
This doesn't harm anyone and would save me some lines of 
error_reporting() changes. Thanks!
 [2006-12-15 19:32 UTC] davidm at marketo dot com
I agree strongly with brjann's analysis.  Once the language allows overloaded properties on an object, it's completely confusing to say that overloaded array properties are immutable while all other property types are mutable, and also that non-overloaded array properties can be iterated with foreach but overloaded array properties cannot be iterated.

I've got a significant amount of code that will have to be rewritten because of this change.  The symfony framework encourages a design pattern that uses overloaded properties on the action objects and any instances where the overloaded property is an array are now broken. 

Other symfony users have run into the problem as well (http://www.symfony-project.com/forum/index.php/m/15684/#msg_15684).

David Morandi
 [2006-12-22 12:20 UTC] tim dot pickup at gmail dot com
Just adding a comment to say this "feature" is also going to cause me a lot of pain changing code.

Any reason it is "expected behaviour" or do we just get a 4 word reply basically saying **** you ?
 [2007-01-06 10:19 UTC] slavikus at gmail dot com
I do agree with the brjann points and also vote for this 
behavior to be fixed; there's no way for me to knowing if any 
particular property is overloaded or not, neither it is right 
to treat them differently from any other properties.
 [2007-01-10 16:01 UTC] dmitry@php.net
Fixed in CVS HEAD and PHP_5_2.
 [2008-01-22 16:36 UTC] lsmith@php.net
I am still seeing this issue on PHP 5.2.5.

Here is a link to a PEAR class affected:
http://pear.php.net/bugs/bug.php?id=10702

The method in question can be found here:
http://pear.php.net/package/XML_Feed_Parser/docs/latest/__filesource/f
source_XML_Feed_Parser__XML_Feed_Parser-1.0.2ParserType.php.html#a189

Changing 

$this->idMappings[$id] = $this->entries[$offset];

to

$mappings = $this->idMappings;
$mappings[$id] = $this->entries[$offset];
$this->idMappings = $mappings;

fixes the notice ..
 [2008-01-24 16:42 UTC] mail at jfcom dot de
For me it's hard to understand, what it should be, that you call fixed. I searched quite a while, but I came to the conclusion, that fixing was just closing the thread?
If it stays as it is, the overloading in case of __get and __set is completely useless, because noone limits himself to simple variables or uses such sick constructs. Is it really the solution to read the whole array, modify it the way you need and write it back as lsmith posted? Come on...
 [2008-01-29 11:31 UTC] dmitry@php.net
The original test-cases from first post and from [19 Nov 2006 11:53am UTC] work fine for me. The following code is not covered by this.

$this->idMappings[$id] = $this->entries[$offset];

The warning message is expected here.

You can fix it by redefining __get() with return by reference.
 [2008-02-06 01:00 UTC] 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-07-03 22:16 UTC] fkwin at web dot de
Not fixed in PHP 5.2.4.
Is there any plan to fix this bug?

I entirely agree with brjann that "normal" and overloaded properties should behave the same. Overloaded array properties should be possible.
 [2008-07-21 09:45 UTC] adam at limabean dot co dot za
Still not fixed in 5.2.5
 [2008-07-21 11:33 UTC] pstradomski at gmail dot com
Works correctly for me on 5.2.6. Did you forget to add the & before __get definition?
 [2008-07-21 17:48 UTC] jani@php.net
It's fixed. Please RTFM next time. (if this is not covered by the manual, open a new bug report with 'Documentation problem' as the category.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 07:01:29 2024 UTC