ZetCode

PHP variable scope

last modified May 18, 2025

Welcome to this tutorial on variable scope in PHP! Understanding how and where variables can be accessed within a program is crucial for writing efficient and error-free code.

Scope refers to the context in which a variable is defined and determines its accessibility within different parts of a program. Depending on where a variable is declared, it may be available only within a specific function, throughout an entire script, or retain its value between function calls.

PHP provides several types of variable scope, including local, global, static, and function parameters. Mastering these scopes will help you structure your code effectively, avoid unexpected behavior, and improve maintainability.

Local scope

Variables declared within a function have local scope and are only accessible within that function. This isolation prevents naming conflicts and makes functions self-contained.

local_scope.php
<?php

declare (strict_types=1);

function calculateTotal() {
    $price = 100; // Local variable
    $tax = $price * 0.08;
    return $price + $tax;
}

echo "Total: " . calculateTotal() . "\n";

// This would cause an error - $price not accessible here
// echo "Price: $price\n";

function testScope() {
    $price = 200; // Different local variable
    echo "Inside function: $price\n";
}

testScope();

This demonstrates local variable scope. Each $price variable exists only within its function. Attempting to access them outside their function would result in an undefined variable error.

λ php local_scope.php
Total: 108
Inside function: 200

Global scope

Variables declared outside functions have global scope. To access global variables inside functions, you must use the global keyword or $GLOBALS array.

global_scope.php
<?php

declare (strict_types=1);

$globalVar = "I'm global"; // Global variable

function testGlobal() {
    global $globalVar; // Access global variable
    echo "Inside function (global keyword): $globalVar\n";
    
    echo "Inside function (GLOBALS array): " . 
         $GLOBALS['globalVar'] . "\n";
    
    $globalVar = "Modified inside function";
}

testGlobal();
echo "After modification: $globalVar\n";

// Another global variable
$counter = 0;

function incrementCounter() {
    global $counter;
    $counter++;
}

incrementCounter();
incrementCounter();
echo "Counter: $counter\n";

This shows how to access and modify global variables within functions. Changes made to globals inside functions persist after the function call. The global keyword and $GLOBALS array provide equivalent access.

λ php global_scope.php
Inside function (global keyword): I'm global
Inside function (GLOBALS array): I'm global
After modification: Modified inside function
Counter: 2

Static variables

Static variables retain their value between function calls while remaining local to the function. They're initialized only once when first encountered.

static_variables.php
<?php

declare (strict_types=1);

function counter() {
    static $count = 0; // Static variable
    $count++;
    echo "Count: $count\n";
}

counter(); // Count: 1
counter(); // Count: 2
counter(); // Count: 3

function rememberValues() {
    static $values = [];
    $values[] = rand(1, 100);
    echo "Values: " . implode(', ', $values) . "\n";
}

rememberValues();
rememberValues();
rememberValues();

This demonstrates static variables preserving their values between function calls. Unlike regular local variables, static variables aren't reinitialized on each function call, making them useful for counters and caches.

λ php static_variables.php
Count: 1
Count: 2
Count: 3
Values: 42
Values: 42, 17
Values: 42, 17, 89

Function parameters

Function parameters have local scope within the function. By default, arguments are passed by value, but they can be passed by reference using &.

function_parameters.php
<?php

declare (strict_types=1);

function square($num) { // Pass by value
    $num *= $num;
    return $num;
}

$value = 5;
echo "Square: " . square($value) . "\n";
echo "Original value: $value\n"; // Unchanged

function addPrefix(&$str) { // Pass by reference
    $str = "Mr. " . $str;
}

$name = "Smith";
addPrefix($name);
echo "Modified name: $name\n"; // Changed

function setDefault($param = 10) { // Default value
    echo "Parameter: $param\n";
}

setDefault(42);
setDefault();

This shows function parameter scope and behavior. Pass-by-value parameters create copies, while pass-by-reference parameters modify the original. Default values are used when arguments aren't provided.

λ php function_parameters.php
Square: 25
Original value: 5
Modified name: Mr. Smith
Parameter: 42
Parameter: 10

Variable scope in included files

Variables declared in the main script are available in included files, while variables declared in included files depend on where they're included.

config.php.php
<?php

declare (strict_types=1);

$dbHost = 'localhost';
$dbUser = 'admin';

This is the config.php file. It contains database configuration variables that can be included in other scripts.

main.php
<?php

declare (strict_types=1);

$mainVar = "From main script";

include 'config.php';

function testIncludedVars() {
    global $dbHost;
    echo "DB Host inside function: $dbHost\n";
}

echo "DB User: $dbUser\n";
testIncludedVars();
echo "Main var: $mainVar\n";

This demonstrates variable scope with included files. Variables from the main script and included files share global scope unless declared inside functions. Proper organization prevents naming conflicts.

λ php included_vars.php
DB User: admin
DB Host inside function: localhost
Main var: From main script

Closures and the 'use' keyword

Anonymous functions (closures) can inherit variables from the parent scope using the use keyword. This creates a closure that "closes over" the specified variables.

closures.php
<?php

declare (strict_types=1);

$factor = 10;

// Closure with 'use' keyword
$multiplier = function($n) use ($factor) {
    return $n * $factor;
};

echo "Multiplier: " . $multiplier(5) . "\n";

// Variables are bound by value unless specified by reference
$counter = 0;
$increment = function() use (&$counter) {
    $counter++;
};

$increment();
$increment();
echo "Counter: $counter\n";

// Using multiple variables
$prefix = "User";
$suffix = "Active";
$format = function($name) use ($prefix, $suffix) {
    return "$prefix: $name ($suffix)";
};

echo $format("Alice") . "\n";

This shows how closures capture variables from the parent scope. By default, variables are passed by value. The & modifier enables pass-by- reference to modify the original variable.

λ php closures.php
Multiplier: 50
Counter: 2
User: Alice (Active)

Superglobals

PHP provides special superglobal variables that are accessible from any scope without the global keyword. These contain server, request, and environment information.

superglobals.php
<?php

declare (strict_types=1);

// Accessing superglobals
echo "Your IP: {$_SERVER['REMOTE_ADDR']}\n";
echo "PHP Version: {$_SERVER['PHP_VERSION']}\n";

// Working with $_GET parameters
// Assume URL: script.php?name=Alice&age=30
echo "Name: {$_GET['name']}\n";
echo "Age: {$_GET['age']}\n";

// Session example
session_start();
$_SESSION['visits'] = ($_SESSION['visits'] ?? 0) + 1;
echo "Session visits: {$_SESSION['visits']}\n";

// Cookie example
$cookieName = 'test_cookie';
$_COOKIE[$cookieName] = 'cookie_value';
echo "Cookie: {$_COOKIE[$cookieName']}\n";

This demonstrates common superglobal variables. These special arrays are always available and provide access to request data, server information, sessions, cookies, and more.

λ php superglobals.php
Your IP: 127.0.0.1
PHP Version: 8.2.5
Name: Alice
Age: 30
Session visits: 1
Cookie: cookie_value

Best practices

Proper variable scope management improves code quality and prevents bugs. Follow these guidelines for effective scope usage.

best_practices.php
<?php

declare (strict_types=1);

// 1. Minimize global variables
$config = []; // Limited globals for configuration

// 2. Use function parameters and return values instead of globals
function calculateArea($width, $height) {
    return $width * $height;
}

// 3. Use static variables for function persistence
function getUniqueId() {
    static $id = 0;
    return ++$id;
}

// 4. Be explicit with variable scope
function processUser($user) {
    global $config; // Explicit global declaration
    
    if (empty($user)) {
        return false;
    }
    
    static $cache = []; // Static cache
    
    if (isset($cache[$user['id']])) {
        return $cache[$user['id']];
    }
    
    // Process user...
    $cache[$user['id']] = $user;
    return $user;
}

// 5. Use closures effectively
$logger = function($message) use ($config) {
    $prefix = $config['log_prefix'] ?? '';
    echo "[$prefix] $message\n";
};

// 6. Avoid modifying superglobals directly
$cleanGet = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);

// 7. Use dependency injection instead of globals
class UserService {
    private $db;
    
    public function __construct($db) {
        $this->db = $db;
    }
    
    public function getUser($id) {
        // Use $this->db instead of global $db
    }
}

These best practices help manage variable scope effectively. Minimizing globals, using proper encapsulation, and being explicit about scope leads to more maintainable and less error-prone code.

Understanding PHP variable scope is fundamental to writing robust applications. Local scope provides isolation, global scope enables shared access when needed, and static variables offer persistence. Proper scope management prevents naming conflicts and makes code more predictable and maintainable.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all PHP tutorials.