← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Global Variable Abuse

Code Quality PHP 5.0+ Intermediate
debt(d5/e7/b7/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpcs, phpstan, and semgrep — all specialist static analysis tools that require deliberate configuration. The code_pattern (global keyword in function bodies, $GLOBALS usage, static class properties as global registry) is mechanically detectable but not caught by the compiler or a default linter pass; you need to enable specific sniffs or rules.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix says 'Replace global variables with constructor injection', which sounds local, but the common_mistakes show globals embedded in database connections, request state, and service wiring — patterns that permeate function boundaries. Replacing each global with injected dependencies requires touching every function signature and call site that previously relied on globals, making this a cross-cutting refactor rather than a single-file fix.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (e7). applies_to covers web, cli, and queue-worker contexts — the full range of PHP execution modes. Global state shapes every function and test written afterward: unit tests must pre-populate globals, concurrency in long-running processes is unsafe, and adding new features means reasoning about implicit state everywhere. The tags (oop, design) underscore that this is an architectural positioning choice affecting how the whole codebase is structured.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap — a documented gotcha most devs eventually learn' (t5). The misconception field states developers believe globals are fine for small scripts and misunderstand PHP-FPM's process model (globals persist within a request but not across requests). This is a well-documented PHP gotcha that catches intermediate developers who reason by analogy from other runtimes or script-scoped languages, but it is a known and documented pitfall rather than a catastrophic contradiction of widely-held assumptions.

About DEBT scoring →

Also Known As

global keyword global state $GLOBALS

TL;DR

Using global variables or the global keyword to share state between functions — making code unpredictable, untestable, and impossible to reason about.

Explanation

Global variables create hidden dependencies: any function anywhere can read or modify them, making execution order critical and side effects unpredictable. In PHP, the global keyword imports a variable from the global scope into a function. PHP superglobals ($_GET, $_POST, $_SESSION) are a necessary evil but accessing them deep in business logic is the same problem. The fix is dependency injection — pass state explicitly as parameters or constructor arguments.

Common Misconception

Global variables are fine for small scripts — even small scripts become hard to test when globals are used; PHP-FPM's process model means globals persist across the request but not between requests, creating subtle bugs.

Why It Matters

Global variables make unit testing impossible without setting up the global state, make concurrency dangerous, and cause subtle bugs when execution order changes.

Common Mistakes

  • Using the global keyword in functions instead of passing parameters.
  • Storing request state in global variables instead of a request context object.
  • Database connection stored in a global variable instead of injected into services.
  • Using static class properties as global state — same problem, different syntax.

Code Examples

✗ Vulnerable
// Global variable abuse:
$db = new PDO(DSN, USER, PASS); // Global

function getUser(int $id): array {
    global $db; // Hidden dependency — untestable without real DB
    return $db->query('SELECT * FROM users WHERE id = ' . $id)->fetch();
}

function saveUser(array $data): void {
    global $db; // Same hidden dependency everywhere
    $db->query('INSERT INTO users ...');
}
✓ Fixed
// Dependency injection — explicit, testable:
class UserRepository {
    public function __construct(private PDO $db) {}

    public function find(int $id): array {
        $stmt = $this->db->prepare('SELECT * FROM users WHERE id = ?');
        $stmt->execute([$id]);
        return $stmt->fetch();
    }
}
// In tests: inject a mock PDO — no global state

Added 16 Mar 2026
Edited 5 Apr 2026
Views 48
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 1 ping S 0 pings M 1 ping T 2 pings W 1 ping T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 2 pings T 0 pings W
No pings yet today
Bing 1 PetalBot 1
Amazonbot 9 Perplexity 5 Scrapy 5 Ahrefs 4 Google 4 Majestic 2 Unknown AI 2 Claude 2 PetalBot 2 Meta AI 1 Bing 1
crawler 34 crawler_json 3
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Replace global variables with constructor injection — globals make functions hard to test, create hidden coupling, and cause race conditions in long-running processes
📦 Applies To
PHP 5.0+ any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
global $db $config in function bodies; $GLOBALS superglobal usage; static class properties used as global registry
Auto-detectable: ✓ Yes phpcs phpstan semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: High Context: File Tests: Update
CWE-1108


✓ schema.org compliant