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

Proxy Pattern

Code Quality PHP 5.0+ Intermediate
debt(d7/e5/b3/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). PHPStan (listed) won't flag missing proxy abstraction or business logic leaking into a proxy; this is a design concern that requires code review.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). Introducing or correcting a proxy means extracting an interface, adjusting the real subject, the proxy class, and likely all call sites/factories — not a one-line fix.

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

Closest to 'localised tax' (b3). Per applies_to, a proxy is a structural pattern around a specific subject; it adds an indirection layer maintainers must keep in sync with the real interface, but its reach stays within that component.

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

Closest to 'notable trap most devs eventually learn' (t5). Per misconception, developers routinely conflate proxy with decorator since both share an interface and wrap a subject; the distinction (controlled access vs added behaviour) is a well-documented gotcha.

About DEBT scoring →

Also Known As

proxy virtual proxy protection proxy caching proxy

TL;DR

Provides a surrogate object that controls access to another object, adding indirection for lazy loading, caching, logging, or access control.

Explanation

The Proxy pattern places an intermediary in front of a real object, implementing the same interface. Types: Virtual Proxy (defers expensive object creation until needed — lazy loading), Caching Proxy (caches results of operations on the real object), Protection Proxy (enforces access control), and Remote Proxy (represents an object in a different process or server). In PHP, Doctrine ORM uses virtual proxies for lazy-loaded entities. The Proxy differs from Decorator in intent: Decorator adds behaviour, Proxy controls access. PHP's magic methods (__get, __call) enable dynamic proxy creation.

Common Misconception

Proxy and decorator patterns are interchangeable. Proxies control access to an object (lazy loading, caching, access control) while decorators add behaviour. A proxy typically has a reference to the real subject from construction; a decorator receives it via injection.

Why It Matters

A proxy controls access to another object — it can add caching, logging, access control, or lazy initialisation transparently without changing the real object or its callers.

Common Mistakes

  • Not implementing the same interface as the real subject — callers must change to use the proxy.
  • Proxy that adds logic the real object should have — the proxy should be transparent infrastructure, not business logic.
  • Virtual proxies that initialise the real object eagerly — defeating the lazy loading purpose.
  • Confusing proxy (same interface, controlled access) with decorator (same interface, added behaviour) — they serve different purposes.

Code Examples

✗ Vulnerable
// Direct access — no caching, no access control:
class ReportService {
    public function getExpensiveReport(int $id): Report {
        return $this->db->runHeavyQuery($id); // Called every time
    }
}
// A CachingReportProxy would intercept and cache without changing ReportService
✓ Fixed
interface Image {
    public function render(): string;
}

class RealImage implements Image {
    public function __construct(private string $path) {
        $this->loadFromDisk(); // expensive
    }
    public function render(): string { return "<img src='{$this->path}'>"; }
}

// Lazy-loading proxy — defers expensive load until render() is first called
class LazyImage implements Image {
    private ?RealImage $real = null;
    public function __construct(private string $path) {}
    public function render(): string {
        $this->real ??= new RealImage($this->path);
        return $this->real->render();
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 47
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
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 2 pings F 0 pings S 1 ping S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 1 ping F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W
No pings yet today
Brave Search 1
Amazonbot 7 ChatGPT 6 Ahrefs 4 PetalBot 4 Perplexity 3 Google 3 Bing 2 Claude 2 Scrapy 2 Brave Search 2 Meta AI 1 Twitter/X 1 Applebot 1
crawler 32 crawler_json 6
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Use a proxy when you need to control access to an object (access control, logging, lazy initialisation) without changing its interface
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Access control or lazy loading logic mixed directly into the real object instead of a transparent proxy
Auto-detectable: ✗ No phpstan
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update


✓ schema.org compliant