#20065 [NEW]: References to object members seem to be backwards
| From: | mattb at columbia dot edu | Date: | Thu, 24 Oct 2002 18:22:12 +0000 |
| Subject: | #20065 [NEW]: References to object members seem to be backwards | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-23220@lists.php.net to get a copy of this message | ||
From: mattb@columbia.edu
Operating system: GNU/Linux 2.4.18-17.7.x (RedHat)
PHP version: 4.2.3
PHP Bug Type: Class/Object related
Bug description: References to object members seem to be backwards
I have stumbled onto a reference behavior I cannot explain. Here's my
problem: I'm trying to return a copy of a member variable. The function is
not declared to return a reference, but it seems as if the user can
override this. Here's a non-object example:
<?php
// Create an array
$array = array('foo', 'bar', 'baz');
// This function merely returns a copy of the array
function testArray()
{
global $array;
return $array;
}
// Grab the return from the function (notice the '&')
$copiedArray = &testArray();
// Modify it
$copiedArray[] = 'quux';
// Print the original and the copy out
echo "=== array ===\n";
var_dump($array);
echo "=== copiedArray ===\n";
var_dump($copiedArray);
?>
Running this yields exactly what you would expect:
=== array ===
array(3) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(3) "baz"
}
=== copiedArray ===
array(4) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(3) "baz"
[3]=>
string(4) "quux"
}
So far, so good. This is as expected (even if the caller tries to use the
'&', he's getting the reference to the copy). Now instead of a global
array, let's try the exact same thing with a member of a global object:
<?php
// Dummy class
class Test
{
var $array;
}
// Instantiate it
$object = &new Test();
// Create a member that is an array
$object->array = array('baz', 'bar', 'foo');
// Same function as before, only it's returning a
// member variable
function testObject()
{
global $object;
return $object->array;
}
// Grab the return from the function (notice the '&')
$copiedArray = &testObject();
// Modify it
$copiedArray['lyx'] = 'quux';
// Print the original and the copy out
echo "=== array ===\n";
var_dump($object->array);
echo "=== copiedArray ===\n";
var_dump($copiedArray);
?>
Here, I would expect that the results would be exactly the same (remember,
there are absolutely no references in the declaration of testObject() or
in the body; everything *should* be a copy). Here's what gets printed when
this is run:
=== array ===
array(4) {
[0]=>
string(3) "baz"
[1]=>
string(3) "bar"
[2]=>
string(3) "foo"
["lyx"]=>
string(4) "quux"
}
=== copiedArray ===
array(4) {
[0]=>
string(3) "baz"
[1]=>
string(3) "bar"
[2]=>
string(3) "foo"
["lyx"]=>
string(4) "quux"
}
Whoa! $copiedArray is now a reference for the member variable! But look
what happens if I redefine the function slightly:
function testObject()
{
global $object;
$array = &$object->array;
return $array;
}
Now I get what I expect again ($copiedArray doesn't point to the member
variable after calling testObject()). So what gives? Why is "return
$object->member;" exempt from the return declaration of the function? This
is an interesting "feature". Not very intuitive...I'd call it a bug. Has
anyone else noticed this? The above behavior happens with scalars (e.g.,
strings, numbers) too, not just arrays.
Now for something REALLY weird. Check this out:
<?php
// Dummy class
class Test
{
var $myString;
}
// Instantiate it
$object = &new Test();
// Create a member
$object->myString = 'hello';
// Test function
function testObject()
{
global $object;
// Make a copy of the member variable (no '&')
$newString = $object->myString;
// Return the COPY
return $newString;
}
// Grab the return from the function (notice the '&')
$copiedString = &testObject();
// Modify it
$copiedString = 'goodbye';
// Print the original and the copy out
echo "=== array ===\n";
echo $object->myString . "\n";
?>
Here's the output:
=== array ===
goodbye
Huh?! I even made a copy inside the function! Note that just as before
(see original message), the following change "fixes" things:
function testObject()
{
global $object;
// Create a reference to the member variable
$newString = &$object->myString;
// Return the reference
return $newString;
}
Now the output is as expected(?):
=== array ===
hello
So (at least according to these tests) it seems that reference handling of
object data members is somewhat inconsistent with the rest of the world
(and of the PHP language specification, from what I understand).
--
Edit bug report at http://bugs.php.net/?id=20065&edit=1
--
Try a CVS snapshot: http://bugs.php.net/fix.php?id=20065&r=trysnapshot
Fixed in CVS: http://bugs.php.net/fix.php?id=20065&r=fixedcvs
Fixed in release: http://bugs.php.net/fix.php?id=20065&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=20065&r=needtrace
Try newer version: http://bugs.php.net/fix.php?id=20065&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=20065&r=support
Expected behavior: http://bugs.php.net/fix.php?id=20065&r=notwrong
Not enough info: http://bugs.php.net/fix.php?id=20065&r=notenoughinfo
Submitted twice: http://bugs.php.net/fix.php?id=20065&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=20065&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=20065&r=php3
Daylight Savings: http://bugs.php.net/fix.php?id=20065&r=dst
IIS Stability: http://bugs.php.net/fix.php?id=20065&r=isapi