When a language is defined by its implementation rather than a standard, it can sometimes be tricky to decide what should be considered correct behaviour and what should be considered an implementation bug.
What follows isn’t so much a PHP trick as a fix for something that really should work, but doesn’t. Although the manual implies that the behaviour described below is specific to Zend Engine 1, all my tests were performed against Zend Engine 2.2, PHP 5.2.5.
Quoting from the manual:
The Zend Engine 1, driving PHP 4, implements the static and global modifier for variables in terms of references. For example, a true global variable imported inside a function scope with the global statement actually creates a reference to the global variable. This can lead to unexpected behaviour which the following example addresses:
<?php function test_global_ref() { global $obj; $obj = &new stdclass; } function test_global_noref() { global $obj; $obj = new stdclass; } test_global_ref(); var_dump($obj); test_global_noref(); var_dump($obj); ?>Executing this example will result in the following output:
NULL
object(stdClass)(0) {}
The example above uses instances of stdClass, but attempts to assign references to scalar values, arrays or resources to global variables have the same result: the attempt to modify the global fails without error (even with error_reporting(E_ALL)), and the global retains whatever value it had before the function call.
The workaround is very simple - assign the reference via the $GLOBALS superglobal:
<?php
function test_global_ref()
{
$GLOBALS['obj'] = &new stdclass;
}
test_global_ref();
var_dump($obj);
Outputs:
object(stdClass)#1 (0) { }
I think one of these scripts must expose an implementation bug - either assigning a reference to a global variable should work, in which case the first script should not fail, or it should not work and the second script should fail. It would be interesting to get an opinion from someone involved in language internals on how PHP should behave. In either case, it’s very hard to understand why the first script doesn’t currently cause a notice or error to be thrown when the assignment fails.
Tags: php
3 comments
Comments feed for this article
Trackback link
http://www.otton.org/2008/11/09/neat-php-tricks-assign-references-globals-workaround/trackback/
November 10, 2008 at 5:11 pm
pestaa
In your first script, “global $obj;” creates a reference, that attaches $obj to $GLOBAL["obj"]; .
When you perform the following action, you redefine local $obj variable to be a reference of a newly created stdClass. In this case, your global variable isn’t touched at all. That is the expected way, and PHP just does it well.
(Of course, in the second example, you directly rewrite the global var, explicitly create a reference to a stdClass.)
Hope this helps. However, if I have misunderstood something, correct me please.
November 10, 2008 at 5:23 pm
David Otton
pestaa: I think that’s a pretty clear explanation of what’s going on, thanks.
November 10, 2008 at 5:32 pm
pestaa
You’re welcome. :) We’re in that lucky situation that PHP is really well-documented. Always refer to there to figure out strange behaviors.