PHP 8.1: $GLOBALS variable restrictions
$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.