ID: 20065 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] -Status: Open +Status: Verified Bug Type: Class/Object related Operating System: GNU/Linux 2.4.18-17.7.x (RedHat) PHP Version: 4.2.3 -Assigned To: +Assigned To: john New Comment:
Very strange... return $object->array; should return a copy of the member variable $array, not a reference. This is of course assuming the function isn't designed to return a reference (denoted by a & in the function declaration)... You note that $foo = &$object->array; return $foo Which leads me to believe this is actually a real bug and not a "feature"... Hence I'm changing the status to Verified When I get a moment I'm going to investigate this a little bit, but it wouldn't surprise me to see this cleaned up in ZE2. Previous Comments: ------------------------------------------------------------------------ [2002-10-24 13:22:12] [EMAIL PROTECTED] 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 this bug report at http://bugs.php.net/?id=20065&edit=1