Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

PHP Dictionary

  1. Home
  2. PHP Dictionary
  3. Variable Scope (global / static)

Variable Scope (global / static)

The range within which a variable can be referenced and assigned is called its "scope." In『PHP』, the scope inside and outside a function is completely separated, and stricter rules apply than in many other languages. Using global declarations or static local variables allows state to be managed across scopes, but incorrect use can become a source of bugs, so care is needed.

Types of Scope

Scope typeDescription
Global scopeThe scope that variables defined outside functions and classes belong to. Variables declared at the top level of a script belong here.
Local scopeThe scope valid inside a function. Variables defined inside a function cannot be accessed from outside. Global variables defined outside the function are also not automatically accessible inside the function.
Static local variable (static)A variable declared with『static』inside a function. Its value is not discarded when the function returns; it carries over to the next call.
Global variable (global declaration)Declaring『global $variableName』inside a function gives access to the variable in the global scope.
Closure use captureThe mechanism by which an anonymous function (closure) captures external variables. Specifying『use ($var)』captures by value; specifying『use (&$var)』captures by reference.

Scope Rules

Syntax / keywordBehavior
Direct access to a global variable from inside a functionNot possible. Using the same variable name as a global variable inside a function treats it as a separate, distinct variable.
global $variableNameCreates an alias to the global-scope variable inside the function. Both reading and writing become possible.
$GLOBALS['variableName']A superglobal array for referencing global variables. Can be accessed from anywhere without a global declaration.
static $variableNameDeclared inside a function. The value is retained when the function exits and is available the next time the same function is called.
use ($variableName)Copies the value of the variable at the time the closure is defined.
use (&$variableName)The closure captures the external variable by reference. Changes made inside the closure are reflected in the external variable.

Sample Code

Function scope basics (cannot touch outside variables)
scope_basic.php
<?php
// Sample confirming the basics of PHP function scope
// A global variable defined outside a function cannot be referenced directly inside the function

$pilotName = "Ikari Shinji"; // global variable

function launchEva(): void {
	// $pilotName is a global variable, but it cannot be referenced inside the function
	// $pilotName here is treated as a separate, undefined variable
	echo "Pilot: " . $pilotName . "\n"; // nothing output (undefined variable)
	echo "Launching.\n";
}

launchEva();

// Can be referenced normally outside the function
echo "Global: " . $pilotName . "\n";

Running the code produces the following output:

php scope_basic.php
Pilot:
Launching.
Global: Ikari Shinji
Accessing a global variable with a global declaration
scope_global.php
<?php
// Sample using a global declaration to access a global variable
// A global declaration allows reading and writing a global variable inside a function

$syncRate = 0.0; // pilot synchronization rate (global variable)
$missionLog = ""; // mission log (global variable)

function updateSyncRate(float $rate): void {
	// The global declaration creates a reference to the global variable
	global $syncRate, $missionLog;

	$syncRate = $rate;
	$missionLog .= "Sync rate updated to " . $rate . "%.\n";
}

function reportStatus(): void {
	// A global declaration is also required here
	global $syncRate, $missionLog;

	echo "Current sync rate: " . $syncRate . "%\n";
	echo "Log:\n" . $missionLog;
}

updateSyncRate(41.3);
updateSyncRate(141.7);
reportStatus();

Running the code produces the following output:

php scope_global.php
Current sync rate: 141.7%
Log:
Sync rate updated to 41.3%.
Sync rate updated to 141.7%.
Accessing via the $GLOBALS superglobal array
scope_globals.php
<?php
// Sample accessing global variables with the $GLOBALS array
// Global variables can be referenced and modified from anywhere without a global declaration

$nerv_hq = "Third Tokyo City";
$alertLevel = 1;

function raiseAlert(int $level): void {
	// $GLOBALS gives access to global variables without a global declaration
	$GLOBALS['alertLevel'] = $level;
	echo $GLOBALS['nerv_hq'] . ": Alert level raised to " . $level . ".\n";
}

raiseAlert(3);
raiseAlert(5);

echo "Final alert level: " . $alertLevel . "\n";

Running the code produces the following output:

php scope_globals.php
Third Tokyo City: Alert level raised to 3.
Third Tokyo City: Alert level raised to 5.
Final alert level: 5
Retaining state with a static local variable
scope_static.php
<?php
// Sample using a static variable to retain state across function calls
// A static local variable retains its value even after the function returns

function countAngel(): int {
	// A statically declared variable is initialized only on the first call
	// From the second call onward, the previous value is carried over
	static $count = 0;

	$count++;
	return $count;
}

// Even when the function is called repeatedly, $count accumulates
echo "Angel #" . countAngel() . " approaching\n";
echo "Angel #" . countAngel() . " approaching\n";
echo "Angel #" . countAngel() . " approaching\n";
echo "Angel #" . countAngel() . " approaching\n";

echo "\n";

// Example of a cache using a static variable
// Returns the saved result on subsequent calls for the same input without recalculating
function getEvaUnit(int $unitNo): string {
	static $cache = []; // array for caching results (retained with static)

	if (isset($cache[$unitNo])) {
		echo "(returning from cache)\n";
		return $cache[$unitNo];
	}

	// Assume a heavy computation or external access would happen here
	$result = "Evangelion Unit-" . $unitNo;
	$cache[$unitNo] = $result;
	return $result;
}

echo getEvaUnit(1) . "\n";
echo getEvaUnit(2) . "\n";
echo getEvaUnit(1) . "\n"; // cache is used

Running the code produces the following output:

php scope_static.php
Angel #1 approaching
Angel #2 approaching
Angel #3 approaching
Angel #4 approaching

Evangelion Unit-1
Evangelion Unit-2
(returning from cache)
Evangelion Unit-1
Closure use capture and scope
scope_closure_use.php
<?php
// Sample of a closure (anonymous function) capturing external variables
// Note the difference between capture by value and capture by reference via use

$pilotName = "Ayanami Rei";
$unitNo = 0;

// --- Capture by value (default for use) ---
// The value is copied at the time the closure is defined
// Changing $pilotName later does not affect the closure
$greetByValue = function() use ($pilotName, $unitNo): string {
	return $pilotName . ", launching in Unit-" . $unitNo . ".";
};

// Changing $pilotName does not affect the closure
$pilotName = "Soryu Asuka Langley";
$unitNo = 2;

echo $greetByValue() . "\n"; // The value before the change (Ayanami Rei, Unit-0) is used

echo "\n";

// --- Capture by reference (use (&$var)) ---
// The closure holds a reference to the external variable
// Changes made externally are reflected inside the closure
$syncRate = 0.0;

$updateSync = function(float $rate) use (&$syncRate): void {
	// &$syncRate directly references the external $syncRate
	$syncRate = $rate;
};

$updateSync(83.2);
echo "Sync rate after reference capture: " . $syncRate . "%\n"; // 83.2 is reflected

$updateSync(141.7);
echo "Sync rate after reference capture: " . $syncRate . "%\n"; // 141.7 is reflected

Running the code produces the following output:

php scope_closure_use.php
Ayanami Rei, launching in Unit-0.

Sync rate after reference capture: 83.2%
Sync rate after reference capture: 141.7%

Common Mistakes

Common Mistake 1: Global variable not visible inside a function (forgetting the global keyword)

PHP functions do not automatically reference external global variables. In some other languages (e.g., JavaScript), the scope chain allows accessing outer variables, but in PHP a『global』declaration is required to touch a variable from outside the function. Without the declaration, the variable is treated as undefined.

ng_global_missing.php
<?php
$pilotName = "Ikari Shinji";

function launch(): void {
	// Without the global declaration, $pilotName is a separate, undefined variable
	echo "Pilot: " . $pilotName . "\n"; // nothing output
}

launch();

Running the code produces the following output:

php ng_global_missing.php
Warning: Undefined variable $pilotName in ...
Pilot:

Write the global declaration at the beginning of the function when using global variables inside it.

ok_global_missing.php
<?php
$pilotName = "Ikari Shinji";

function launch(): void {
	global $pilotName; // create a reference to the global variable
	echo "Pilot: " . $pilotName . "\n";
}

launch();

Running the code produces the following output:

php ok_global_missing.php
Pilot: Ikari Shinji

Common Mistake 2: static variable carrying its value over to the next call

A『static』variable retains its value when the function returns. This is intentional behavior, but during testing or processing that spans multiple requests, the value left over from a previous call can produce unexpected results. In unit tests in particular, calling the same function multiple times means the static variable is not reset, so behavior changes.

ng_static_carry.php
<?php
function countAngel(): int {
	static $count = 0;
	$count++;
	return $count;
}

// First call
echo countAngel() . "\n"; // 1

// Subsequent calls carry over the previous value
echo countAngel() . "\n"; // 2 (if a test expects 1 every time, this is a bug)
echo countAngel() . "\n"; // 3

Running the code produces the following output:

php ng_static_carry.php
1
2
3

Using it as a counter or intentional state retention is fine, but when a reset is needed each time, use a regular variable instead of static.

ok_static_carry.php
<?php
// When a reset is needed, design the function to accept the value as a parameter
function countAngelFrom(int $start): int {
	return $start + 1;
}

// The caller manages the counter
$count = 0;
$count = countAngelFrom($count); // 1
echo $count . "\n";
$count = countAngelFrom($count); // 2
echo $count . "\n";
$count = 0; // can be reset at any time
$count = countAngelFrom($count); // 1
echo $count . "\n";

Running the code produces the following output:

php ok_static_carry.php
1
2
1

Common Mistake 3: External changes not reflected because closure use captures by value

The『use』keyword in a closure captures by value by default. The variable's value is copied at the time the closure is defined, so changes to the external variable afterward are not reflected inside the closure. The bug of "the external variable changed, but the closure is still using the old value" is caused by this behavior.

ng_closure_use_value.php
<?php
$pilotName = "Ayanami Rei";

// use by value: "Ayanami Rei" is copied at the time the closure is defined
$greet = function() use ($pilotName): void {
	echo "Pilot: " . $pilotName . "\n";
};

// Changing the external variable after defining the closure is not reflected
$pilotName = "Soryu Asuka Langley";

$greet(); // "Ayanami Rei" is output (external change not reflected)

Running the code produces the following output:

php ng_closure_use_value.php
Pilot: Ayanami Rei

When you want external variable changes to be reflected inside the closure, use capture by reference (『use (&$variableName)』).

ok_closure_use_ref.php
<?php
$pilotName = "Ayanami Rei";

// use (&$pilotName) captures by reference: holds a reference to the external variable
$greet = function() use (&$pilotName): void {
	echo "Pilot: " . $pilotName . "\n";
};

// Changing the external variable after defining the closure is reflected
$pilotName = "Soryu Asuka Langley";

$greet(); // "Soryu Asuka Langley" is output

Running the code produces the following output:

php ok_closure_use_ref.php
Pilot: Soryu Asuka Langley

Summary

『PHP』function scope is stricter than in many other languages; global variables from outside cannot be referenced directly from inside a function.To use a global variable inside a function, either a『global』declaration or the『$GLOBALS』array is required. Both approaches tightly couple the function to external state, making it harder to test and more prone to bugs.Designs that accept values through parameters and return results as return values are the common approach.

『static』local variables are suited for use cases like counting function calls or caching the result of a heavy computation—"state retention that is self-contained within the function." Unlike global variables, they cannot be modified directly from outside, so the side-effect range is limited to within the function.

The closure『use』capture defaults to capture by value, so the value of the variable at the time the closure is defined is copied.To modify an external variable from inside a closure, capture by reference must be made explicit with『use (&$variableName)』.Capture by reference is convenient but tends to cause unintended side effects, so use it sparingly. Arrow functions (『fn』) automatically capture external variables by value, but do not support capture by reference. See『Arrow functions (fn)』for details. For the basics of defining functions, see『Function definitions (function)』.

If you find any errors or copyright issues, please .