Note

Everything below applies to PHP4 and was written in 2008. It’s wildly, wildly out of date.

Neat PHP Tricks: How To Assign References to Globals

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) {}

http://uk2.php.net/static

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.


The original version of this post received a useful explanation from pestaa:

Quote

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.