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

Static Methods & Properties

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

Closest to 'specialist tool catches it' (d5). The detection_hints list PHPStan, Mockery, and PHPUnit — PHPStan can flag static calls in business logic and note that statics cannot be mocked, but this requires deliberate configuration and a specialist SAST mindset. Standard linters don't flag static usage by default; a developer must run PHPStan with appropriate rules. The problem is silent at runtime until tests fail or concurrency issues surface.

e7 Effort Remediation debt — work required to fix once spotted

Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix says 'Replace static utility methods with injected service objects,' but this is not a single-line fix — it requires introducing constructor injection, updating every call site, wiring dependency injection containers, and modifying tests. Because static calls can be spread across many classes and layers (web, cli, queue-worker all listed in applies_to), removal is a cross-cutting refactor. Slightly below e9 because it doesn't require a full architectural rewrite, but it comfortably exceeds multi-file e5.

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

Closest to 'strong gravitational pull' (b7). Static methods apply across web, cli, and queue-worker contexts, meaning every new feature or test written against a statically-coupled class inherits the coupling. The tags include coupling and testing, and the definition notes hidden global dependencies. Each new developer and each new class that calls a static method adds another point of coupling, shaping how the whole codebase is structured around testability. Not quite b9 (the entire system is not redefined), but the gravitational pull is strong and pervasive.

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

Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field explicitly states that developers believe static methods are 'just regular methods that do not need instantiation,' when in fact they create hidden dependencies, cannot be mocked by standard test doubles, and cause test pollution via shared state. This directly contradicts OOP intuitions from instance-based design (where swapping an implementation is straightforward). The trap is well-documented but consistently surprises developers migrating from procedural backgrounds or using Laravel Facades, earning t7.

About DEBT scoring →

Also Known As

PHP static static method static property

TL;DR

Class-level methods and properties that exist independently of any instance — useful for utilities and factories, but harmful when overused.

Explanation

Static methods and properties belong to the class rather than an instance and are called with :: (ClassName::method()). They are appropriate for: pure utility functions (Math::clamp()), named constructors/factories (Money::fromFloat()), and singleton registries. However, static state is global state — it persists across test cases, cannot be easily mocked, and creates hidden dependencies. Static calls are hard to stub in tests without workarounds like Mockery's alias mocking. Prefer instance methods with dependency injection for anything stateful or replaceable; reserve static for genuinely stateless utilities.

Common Misconception

Static methods are just regular methods that do not need instantiation. Static methods are globally accessible shared state — they cannot be mocked by standard test doubles, create hidden dependencies, and make code harder to reason about in concurrent contexts.

Why It Matters

Static methods couple callers to a specific class and cannot be easily mocked or swapped — overusing them creates hidden global dependencies that resist unit testing.

Common Mistakes

  • Using static methods for stateful operations — global state in static methods causes test pollution.
  • Static factory methods that return a concrete type — cannot be overridden in subclasses without LSP violation.
  • Calling static methods on $this inside a class — use self:: or static:: explicitly.
  • Not distinguishing stateless utility statics (Math::round()) from stateful service statics (DB::query()) — the former is fine, the latter is problematic.

Code Examples

✗ Vulnerable
// Static method with global state — cannot be unit tested:
class Database {
    private static ?PDO $connection = null;
    public static function query(string $sql): array {
        return self::getConnection()->query($sql)->fetchAll();
    }
}
// Callers: Database::query() — tightly coupled, untestable without real DB
✓ Fixed
// Static methods: no instance state, utility/factory use cases
class Uuid {
    public static function v4(): string {
        return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }
}
$id = Uuid::v4();

// Named constructors — static factory on a value object
readonly class Temperature {
    private function __construct(public float $celsius) {}
    public static function fromCelsius(float $c): self    { return new self($c); }
    public static function fromFahrenheit(float $f): self  { return new self(($f-32)*5/9); }
    public static function fromKelvin(float $k): self      { return new self($k-273.15); }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 45
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 1 ping T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 1 ping W 1 ping T 0 pings F 0 pings S 3 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 3 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 10 Scrapy 5 Ahrefs 4 Perplexity 3 Google 3 ChatGPT 3 Bing 3 Unknown AI 2 Claude 2 SEMrush 2 PetalBot 2 Meta AI 1
crawler 35 crawler_json 5
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Replace static utility methods with injected service objects — static calls create hidden global dependencies that can't be mocked, swapped, or configured per-context
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Static method calls in business logic; PHPStan cannot mock static; Laravel Facades in domain code; utility class with all static methods
Auto-detectable: ✓ Yes phpstan mockery phpunit
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: Class Tests: Update


✓ schema.org compliant