PHP 8.1: $GLOBALS variable restrictions

Version8.1
TypeChange

$GLOBALS is a special variable in PHP that references all variables in the global scope. $GLOBALS is an associative array, with array keys being the global variable name, and the array key being the global variable. $GLOBALS contains all global variables as well as other super global values such $_SERVER, $_GET, $_ENV, etc. where applicable.

$foo = 'apple';
$GLOBALS['foo'] = 'banana';

echo $foo; // banana

Additionally, the $GLOBALS array was always assigned by reference (prior to PHP 8.1), even if it visibly assigned by-value.

$foo = 'apple';

$my_vars = $GLOBALS;
$my_vars['foo'] = 'banana';

echo $foo; // banana

It adds a significant amount of technical complexity to support this $GLOBALS variable behavior, particularly when the $GLOBALS array itself is modified which affects multiple global variables at once.

$GLOBALS = get_new_vars();

From PHP 8,1 and later, certain changes to the $GLOBALS array throws fatal errors. In general, modifying individual array elements is allowed, but making mass changes are not allowed.

$GLOBALS = get_new_vars();
Fatal error: $GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax in ... on line ...

Restrictions and Changes

All changes that affect the $GLOBALS array itself are not allowed since PHP 8.1. This includes destroying the $GLOBALS array, overwriting it with a new value, array operations, and creating references to $GLOBALS variable.

Mass changes to $GLOBALS are no longer allowed

Overwriting, unsetting, or otherwise making mass changes to the $GLOBALS array is no longer allowed.

For example, the all of the following modifications are allowed prior to PHP 8.1, but results in a fatal error in PHP 8.1 and later:

$GLOBALS = [];
$GLOBALS = ['foo' => 1, 'bar' => 2];
$GLOBALS = get_new_vars();
$GLOBALS =& $new_vars;
list($GLOBALS) = [1];
foreach ($new_var_c as $GLOBALS) {}
unset($GLOBALS);
Fatal error: $GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax in ... on line ...

Referencing $GLOBALS is no longer allowed

Prior to PHP 8.1, it was possible to create a reference to $GLOBALS array, and modify that reference. All changes would then be reflected in the global variables as well.

$x =& $GLOBALS;
$x['foo'] = 'test';

echo $foo; // 'test';

From PHP 8.1, it is no longer allowed to create references to $GLOBALS variable.

$x =& $GLOBALS;
Fatal error: Cannot acquire reference to $GLOBALS in ... on line ...

Further, it is no longer allowed to pass $GLOBALS to a function that expects a parameter by-reference.

array_pop($GLOBALS);
Fatal error: Uncaught Error: array_pop(): Argument #1 ($array) cannot be passed by reference in ...:...

$GLOBALS['GLOBALS'] no longer exists

Prior to PHP 8.1, $GLOBALS variable contained a reference to itself at $GLOBALS['GLOBALS']. It no longer exists in PHP 8.1 and later.

isset($GLOBALS['GLOBALS']); // false

Backwards Compatibility Impact

Applications that mass-modify, unset, or populate the $GLOBALS array might need to perform said operations on individual array keys, or otherwise they will result in fatal errors since PHP 8.1.

Further, creating references to the $GLOBALS variable is no longer allowed, and it no longer behaves as if it was assigned when a standard variable is assigned $GLOBALS (i.e. $var = $GLOBALS).

It is rare for a PHP application to make such changes to the $GLOBALS variable, and more often than not, there is a better approach to achieve the result, either using PSR-7 objects, or using mocking libraries when testing applications.


RFC Discussion Implementation