Variables Scope

La Lakshmi Priya Updated 17 Oct 2026
11 min read ·Lesson 22 of 22

What Is Variable Scope?

In simple terms: Scope is the area of a program where a variable can be seen and used. A variable created in one place is not automatically available everywhere.

Technically: The scope of a variable is the context in which it is defined. PHP has a small number of scopes:

ScopeWhere Variables Are CreatedWhere They Are Visible
GlobalOutside any function (the main script and the files it includes)Only outside functions
Local (function)Inside a function, including its parametersOnly inside that function call
StaticInside a function, declared with staticInside that function; value persists between calls
SuperglobalBuilt in ($_GET, $_POST, $_SERVER, …)Everywhere

Why Scope Exists

Imagine every variable were visible everywhere. A function using $total for its own calculation would overwrite a $total used by the main script, and a library function using $i would break your loop counter. Scope isolates code so that:

  • Functions can use any variable names without colliding with the rest of the program
  • A function's behavior depends only on its inputs (parameters), which makes it predictable and testable
  • Bugs are easier to locate, because a variable can only be changed in a limited area

Global Scope

A variable created outside of any function has global scope. It is available anywhere in the main script — but not inside functions.

Example

<?php
$siteName = "GoLearn";

echo "Welcome to $siteName\n";

function showFooter()
{
    echo "© 2026 $siteName\n";
}

showFooter();

Output

Welcome to GoLearn
PHP Warning:  Undefined variable $siteName in /path/script.php on line 8
© 2026 

Why This Happens

Inside showFooter(), PHP looks for $siteName in the function's local scope only. That scope is empty, so the variable is undefined.

This is a major difference from languages such as JavaScript, where inner functions can automatically read variables from outer scopes. In PHP, a regular function is completely isolated from global variables unless you explicitly bring them in.


Local Scope

A variable created inside a function has local scope. It exists only while that function runs and cannot be accessed from outside.

Example

<?php
function calculateDiscount()
{
    $discountRate = 0.10;
    $discount = 2000 * $discountRate;

    echo "Discount inside function: $discount\n";
}

calculateDiscount();

echo "Discount outside function: $discount\n";

Output

Discount inside function: 200
PHP Warning:  Undefined variable $discount in /path/script.php on line 12
Discount outside function: 

How It Works

  1. When calculateDiscount() is called, PHP creates a new, empty local scope.
  2. $discountRate and $discount are created in that scope.
  3. When the function ends, the local scope and all its variables are destroyed.
  4. Outside the function, $discount never existed.

Each Call Gets a Fresh Scope

<?php
function countVisit()
{
    $count = 0;
    $count++;
    echo "Count: $count\n";
}

countVisit();
countVisit();
countVisit();

Output

Count: 1
Count: 1
Count: 1

Every call starts with an empty scope, so $count is recreated as 0 each time. To keep a value between calls, use a static variable, covered in the next lesson.

Same Names, Different Variables

Because scopes are isolated, a local variable can share a name with a global one without any conflict:

<?php
$total = 999;

function sumItems()
{
    $total = 10 + 20;
    return $total;
}

echo sumItems() . "\n";
echo $total . "\n";

Output

30
999

The function's $total and the global $total are two different variables. The function cannot accidentally overwrite the global value.


Passing Data Into and Out of Functions

The correct way to give a function data is through parameters, and the correct way to get data back is with return.

Example

<?php
$siteName = "GoLearn";
$year = 2026;

function buildFooter(string $name, int $year): string
{
    return "© $year $name. All rights reserved.";
}

echo buildFooter($siteName, $year);

Output

© 2026 GoLearn. All rights reserved.

Why This Is the Preferred Approach

  • Explicit dependencies: The function signature shows exactly what it needs. You do not have to read the function body to discover that it secretly uses a global variable.
  • Reusability: The same function can build footers for different sites or years.
  • Testability: You can call buildFooter("Test", 2000) and check the result without setting up any global state.
  • Safety: The function cannot modify the caller's variables. It only returns a new value.

Parameters are local variables of the function. $name and $year inside buildFooter() are copies of the values passed in. (The parameter $year and the global $year are separate variables that happen to share a name.)


Accessing Global Variables Inside a Function

Sometimes you need to read or modify a global variable from inside a function. PHP provides two mechanisms. Both work, but both should be used sparingly.

The global Keyword

<?php
$visitCount = 0;

function registerVisit()
{
    global $visitCount;
    $visitCount++;
}

registerVisit();
registerVisit();
registerVisit();

echo "Visits: $visitCount";

Output

Visits: 3

How It Works

global $visitCount; creates a local reference to the global variable of the same name. From that line onward, $visitCount inside the function refers to the global variable, so changes affect it directly.

Several variables can be imported at once:

global $dbHost, $dbUser, $dbName;

The $GLOBALS Array

$GLOBALS is a superglobal array that contains every variable in the global scope, with the variable name as the key.

<?php
$taxRate = 0.18;
$price = 1000;

function priceWithTax()
{
    return $GLOBALS['price'] * (1 + $GLOBALS['taxRate']);
}

echo priceWithTax();

Output

1180

$GLOBALS['price'] reads the global $price without a global statement. You can also write to an element: $GLOBALS['price'] = 1200; changes the global variable.

Version note (PHP 8.1+): $GLOBALS is now a read-only copy as a whole. Writing to individual elements still works, but replacing the entire array ($GLOBALS = [];) or passing it by reference is no longer allowed and causes a compile-time error.

global vs $GLOBALS

Aspectglobal $x;$GLOBALS['x']
SyntaxDeclared once, then used as $xArray access on every use
Makes clear it is global at the point of useNo — looks like a normal local variable later in the functionYes — $GLOBALS is visible on every line
Can access a variable whose name is dynamicNoYes — $GLOBALS[$name]
Typical useOlder code, simple scriptsOccasional access, debugging

Why Global Variables Should Be Avoided

Both mechanisms create hidden dependencies:

<?php
function applyDiscount()
{
    global $cartTotal, $discountRate;
    $cartTotal = $cartTotal * (1 - $discountRate);
}

Problems with this function:

  • Its signature says nothing about needing $cartTotal or $discountRate.
  • If any other code changes those globals, applyDiscount() behaves differently.
  • It modifies a global variable, so calling it twice silently applies the discount twice.
  • It cannot be reused for a second cart or tested in isolation.

The same function with parameters and a return value:

<?php
function applyDiscount(float $total, float $rate): float
{
    return $total * (1 - $rate);
}

$cartTotal = applyDiscount($cartTotal, 0.10);

Now every input is visible, nothing is modified behind the caller's back, and the result is explicitly assigned. As applications grow, shared state is usually managed with objects and dependency injection, covered in the PHP OOP section.


PHP Has No Block Scope

In many languages, variables created inside if blocks or loops disappear after the block ends. PHP does not work that way. Braces { } in if, for, foreach, while, and switch do not create a new scope. Only functions (and classes) do.

Example

<?php
$score = 85;

if ($score >= 50) {
    $result = "Pass";
}

echo $result . "\n";

for ($i = 1; $i <= 3; $i++) {
    $lastValue = $i * 10;
}

echo "i = $i, lastValue = $lastValue\n";

Output

Pass
i = 4, lastValue = 30

Why This Matters

  • $result, created inside the if block, is still available afterward.
  • The loop counter $i and $lastValue remain after the loop. $i is 4 because the loop stops when $i <= 3 becomes false.

This is convenient, but it can cause bugs. If the condition is false, the variable is never created:

<?php
$score = 30;

if ($score >= 50) {
    $result = "Pass";
}

echo $result;

Output

PHP Warning:  Undefined variable $result in /path/script.php on line 8

Fix: Initialize the variable before the block, so it exists on every path:

<?php
$score = 30;
$result = "Fail";

if ($score >= 50) {
    $result = "Pass";
}

echo $result;

A related pitfall involves foreach with references, where the reference variable survives the loop and causes unexpected overwrites. It is explained in the Foreach Loop lesson.


Scope of Included Files

When you include or require a file, its code runs in the scope where the include statement appears. Included files do not have their own scope.

config.php

<?php
$appName = "Inventory Manager";
$itemsPerPage = 25;

index.php

<?php
require __DIR__ . '/config.php';

echo "$appName shows $itemsPerPage items per page.\n";

function loadConfigInsideFunction()
{
    require __DIR__ . '/config.php';
    echo "Inside function: $appName\n";
}

loadConfigInsideFunction();

Output

Inventory Manager shows 25 items per page.
Inside function: Inventory Manager

How It Works

  • The first require runs in the global scope, so $appName and $itemsPerPage become global variables.
  • The second require runs inside the function, so the same variables become local to that function call.

This explains why template files can use variables defined by the page that includes them: they run in the page's scope. A cleaner pattern for configuration is a file that returns an array:

<?php
// config.php
return [
    'appName' => 'Inventory Manager',
    'itemsPerPage' => 25,
];
<?php
$config = require __DIR__ . '/config.php';
echo $config['appName'];

Here the configuration arrives as a single, explicitly named value instead of a set of variables appearing silently in the current scope.


Superglobals: Available Everywhere

PHP provides a set of built-in arrays called superglobals that are accessible in every scope — inside functions, methods, and included files — without global.

<?php
function currentPage(): string
{
    return $_SERVER['REQUEST_URI'] ?? '/';
}

function searchTerm(): string
{
    return $_GET['q'] ?? '';
}
SuperglobalContains
$GLOBALSAll global variables
$_SERVERServer and request information
$_GETURL query parameters
$_POSTSubmitted form data
$_FILESUploaded files
$_COOKIECookies sent by the browser
$_SESSIONSession data
$_REQUESTCombined GET, POST, and (by default) COOKIE data
$_ENVEnvironment variables

Each superglobal has its own lesson in the PHP Superglobals section. Only these built-in variables are superglobal; you cannot create your own.


Scope in Anonymous and Arrow Functions

Anonymous functions (closures) and arrow functions are functions too, but they have special ways to use variables from the surrounding code.

Anonymous Function With use

<?php
$taxRate = 0.18;

$addTax = function (float $amount) use ($taxRate): float {
    return $amount * (1 + $taxRate);
};

echo $addTax(500);

Output

590

use ($taxRate) copies the value of $taxRate from the surrounding scope into the closure at the moment the closure is created. Without use, $taxRate would be undefined inside the function, just like in a regular function.

Arrow Function (PHP 7.4+)

<?php
$taxRate = 0.18;

$addTax = fn(float $amount): float => $amount * (1 + $taxRate);

echo $addTax(500);

Output

590

Arrow functions automatically capture variables from the surrounding scope by value. No use clause is needed.

These capture mechanisms are explicit and limited to the specific function, which is why they are safer than global. They are covered fully in Anonymous Functions, Closures, and Arrow Functions.


Practical Example: Order Processing Without Globals

<?php
const TAX_RATE = 0.18;

function calculateSubtotal(array $items): float
{
    $subtotal = 0;

    foreach ($items as $item) {
        $subtotal += $item['price'] * $item['qty'];
    }

    return $subtotal;
}

function calculateTax(float $amount): float
{
    return round($amount * TAX_RATE, 2);
}

$cart = [
    ['name' => 'Notebook', 'price' => 60, 'qty' => 5],
    ['name' => 'Pen', 'price' => 15, 'qty' => 10],
];

$subtotal = calculateSubtotal($cart);
$tax = calculateTax($subtotal);
$total = $subtotal + $tax;

echo "Subtotal: $subtotal\n";
echo "Tax: $tax\n";
echo "Total: $total\n";

Output

Subtotal: 450
Tax: 81
Total: 531

Why This Design Works

  • TAX_RATE is a constant. Unlike variables, constants defined with const or define() are available in every scope, which makes them suitable for fixed configuration values. See PHP Constants.
  • Each function receives everything it needs as parameters and returns its result.
  • The local $subtotal inside calculateSubtotal() and the global $subtotal are separate variables; the global one receives the value through return.
  • No function reads or changes global variables, so each one can be tested and reused independently.

Common Mistakes

Expecting Functions to See Outer Variables

What happens: Warning: Undefined variable inside a function.

Why: Regular PHP functions only see their own local scope.

Fix: Pass the value as a parameter. Use use for closures; arrow functions capture automatically.

Expecting Local Variables to Exist After the Function

What happens: Warning: Undefined variable after calling the function.

Fix: return the value and assign it: $discount = calculateDiscount();.

Overusing global

What happens: Functions depend on and modify hidden state, causing bugs that appear far from their cause.

Fix: Use parameters and return values. Group related shared data into objects.

Using Variables Created Only Inside a Conditional Block

What happens: The variable is undefined when the condition is false.

Fix: Initialize the variable with a default value before the block.

Assuming Loop Variables Disappear

What happens: A later loop or calculation accidentally reuses $i, $item, or $value from an earlier loop.

Fix: Use distinct, descriptive names, and keep longer logic inside functions, which do provide scope isolation.


Best Practices

  • Pass data into functions with parameters, and get data out with return.
  • Avoid global and $GLOBALS in application code; reserve them for small scripts or legacy code.
  • Use constants for fixed configuration values that many functions need.
  • Initialize variables before conditional blocks.
  • Keep functions small, so their local scope stays small and easy to understand.
  • Load configuration from a file that returns an array instead of creating loose global variables.

Official reference: https://www.php.net/manual/en/language.variables.scope.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
Ask about this post
AI Ask about this post

Ask questions about Variables Scope and get answers drawn from it.

Signed-in readers only.