In PHP, how does the global keyword work under the hood, and what did PHP 8.1 change about writing to $GLOBALS?
answer
- global $x is $x = &$GLOBALS['x']
- creates the global as null if missing
- unset only removes the local alias
- rebinding the alias stays local
- 8.1: no writes to the whole array
basics
~20 sglobal $x creates a local reference to the global $x, like $x = &$GLOBALS['x'], so unsetting or rebinding the local name leaves the global alone. Since PHP 8.1, $GLOBALS cannot be written as a whole, only element by element.
solid answer
~40 s`global $config;` binds a **local variable by reference** to the global of the same name; the manual says to think of it as `$config = &$GLOBALS['config'];`. If the global does not exist, it is created with `null`. Because it is a reference, assigning a value through `$config` changes the global, but `unset($config)` only removes the local alias, and `$config = &$other;` only rebinds the local name; to affect the global itself use `$GLOBALS['config']`. `$GLOBALS` is a superglobal, visible in every scope. Since **PHP 8.1**, reading and writing individual elements (`$GLOBALS['config'] = ...`) and reading the whole array still work, but **writing to the whole array** is no longer supported: `array_pop($GLOBALS)` is an error.
code
php · 18 lines<?php
$units = 'metric';
function dropUnits(): void
{
global $units;
unset($units); // removes only the local alias
}
function reallyDropUnits(): void
{
unset($GLOBALS['units']); // removes the global itself
}
dropUnits();
var_dump($units); // string(6) "metric"
reallyDropUnits();
var_dump(isset($units)); // bool(false)go deeper
Recall that global imports a global variable into a function and that $GLOBALS is available everywhere.
Explain that global creates a reference, so unset and reference reassignment only affect the local alias, and state the 8.1 $GLOBALS restriction.
Recognise order-dependent test failures caused by global state and refactor global-based helpers to explicit dependencies.
Plan the removal of global state from a legacy codebase, starting with the values that tests and concurrent workers trip over most.
## What global actually does The `global` statement imports variables from the global scope into the current function: ```php <?php $stationName = 'north'; function label(): string { global $stationName; // like: $stationName = &$GLOBALS['stationName']; return strtoupper($stationName); } ``` The manual describes the mechanism precisely: - A **local variable is created that references** the global variable of the same name. - If the global does **not exist**, it is created in the global scope with the value `null`. - It accepts a list: `global $a, $b;`. - Using `global` outside a function is not an error; it matters when the file is included from inside a function. The key sentence is the equivalence: `global $var;` is a shortcut for `$var = &$GLOBALS['var'];`. Every surprising behaviour follows from it being a **reference**. ## Consequences of being a reference | Inside the function | Effect on the global | |---|---| | `$stationName = 'south';` | changes it, both names share the content | | `unset($stationName);` | none, only the local alias is removed | | `$stationName = &$local;` | none, the local name now points elsewhere | | `$GLOBALS['stationName'] = 'south';` | changes it directly | | `unset($GLOBALS['stationName']);` | removes the global | | `$GLOBALS['stationName'] = &$local;` | rebinds the global to `$local` | The manual shows the rebinding case with two functions: the one that assigns an object by reference to a `global` variable leaves the global `NULL`; the one that assigns normally sets it. The same applies to `unset()`: the manual's `destroy_foo()` example unsets a globalised variable and the global keeps its value. ## $GLOBALS `$GLOBALS` is an associative array of all global variables, keyed by name, and it is a **superglobal**, so it is available in every scope without importing. Reading `$GLOBALS['stationName']` inside a function is equivalent to importing it with `global`, but explicit at every use. ## The PHP 8.1 restriction PHP 8.1 restricted what code can do with `$GLOBALS`: 1. **Still works**: reading and writing individual elements, `$GLOBALS['x']` and `$GLOBALS['x'] = 1`. 2. **Still works**: read-only access to the whole array, such as `foreach ($GLOBALS as $name => $value)`. 3. **No longer supported**: write access to the entire array. The migration guide's example is `array_pop($GLOBALS)`, which now results in an error. Code affected in practice is rare: libraries that reset or bulk-modify all globals, usually in test harnesses. ## When global is still seen `global` appears in legacy code and in a few plugin systems built around global functions. In new code it is a design smell: - the dependency is invisible in the function signature; - any code can change the value between calls; - tests must set up global state and clean it up afterwards, which causes order-dependent test failures. The replacements are parameters, constructor-injected objects and, for true constants, `const`. When you must touch a global in legacy code, `$GLOBALS['name']` is at least explicit at each use and avoids the reference surprises in the table above. ## Interview checklist - `global $x` equals `$x = &$GLOBALS['x']`. - Missing globals are created as `null`. - `unset()` and reference reassignment affect only the local alias. - 8.1: whole-array writes to `$GLOBALS` are an error; element access is unchanged.
- Inside a function, `global $cfg; $cfg = &$local;` does not change the global; why, and how do you fix it?`global $cfg` makes the local `$cfg` a reference to the global content. Assigning another reference to `$cfg` only rebinds the local name; the global slot is untouched. Assign by reference through the array instead, `$GLOBALS['cfg'] = &$local;`, or better, return the value and let the caller assign it.
- Does PHP 8.1 stop you from assigning $GLOBALS['x'] = 5 inside a function?No. Reading and writing individual elements of `$GLOBALS` works as before. What 8.1 removed is write access to the array as a whole, such as `array_pop($GLOBALS)`. Reading the whole array, for example iterating it, also still works.
saying these in an interview costs you the question
- global $x copies the global value into a local variable.
- unset() on a variable imported with global deletes the global.
- Since PHP 8.1, $GLOBALS['x'] = 1 is an error.
- global $x fails if the global variable does not exist yet.
- $GLOBALS must be imported with global before use inside a function.