Global Variable Abuse
debt(d5/e7/b7/t5)
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.
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.
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.
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.
Also Known As
TL;DR
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
Why It Matters
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
// 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 ...');
}
// 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