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

Lazy Objects (PHP 8.4)

php PHP 8.4+ Advanced

Also Known As

lazy proxy lazy ghost lazy initialization ReflectionClass lazy

TL;DR

PHP 8.4 native lazy object proxies defer initialisation until first access — enabling zero-cost dependency injection of services that may never be used in a request.

Explanation

PHP 8.4 adds ReflectionClass::newLazyProxy() and ReflectionClass::newLazyGhost() to the core. A lazy ghost is the real object class with initialisation deferred; a lazy proxy wraps a real instance created on demand. Both defer expensive construction (DB connections, API clients, heavy config parsing) until the first property access or method call. This is the pattern that DI containers have implemented manually for years — now it is a first-class language feature.

Common Misconception

Lazy objects are just lazy loading — lazy objects are native VM-level proxies; property access on a lazy object transparently triggers initialisation with no interface changes to the consuming code.

Why It Matters

A DI container that injects 50 services into a controller only needs to construct the 3 actually used per request — lazy objects make this automatic at the language level.

Common Mistakes

  • Using lazy objects for services that are always accessed — the proxy overhead is wasted if initialisation always happens.
  • Not understanding that lazy ghost requires the real class, while lazy proxy can wrap any compatible class.
  • Serialising lazy objects before initialisation — behaviour depends on whether the object has been triggered.
  • Triggering initialisation in the constructor of the surrounding class — defeats the purpose.

Code Examples

✗ Vulnerable
// Eager construction — all services built even if unused:
class OrderController {
    public function __construct(
        private ReportingService $reporting,  // Heavy — connects to BI DB
        private AuditService $audit,          // Heavy — reads config files
        private NotificationService $notify,  // Heavy — loads templates
    ) {} // All three built on every request, even simple reads
}
✓ Fixed
// PHP 8.4 lazy proxy — only constructed if accessed:
$container->bind(ReportingService::class, function() {
    $reflector = new ReflectionClass(ReportingService::class);
    return $reflector->newLazyProxy(
        fn() => new ReportingService($this->get(BiDatabase::class))
    );
});
// OrderController receives the proxy
// ReportingService only constructed when $this->reporting->method() called

Added 16 Mar 2026
Edited 22 Mar 2026
Views 23
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping F 0 pings S 0 pings S 0 pings 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 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S
No pings yet today
Amazonbot 7 Perplexity 3 ChatGPT 3 Ahrefs 2 Unknown AI 2 Google 1
crawler 17 crawler_json 1
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Use lazy initialisation for expensive objects in DI containers — PHP 8.4 adds native lazy object support via ReflectionClass; otherwise use proxy generators like ocramius/proxy-manager
📦 Applies To
PHP 8.4+ web cli symfony laravel
🔗 Prerequisites
🔍 Detection Hints
Expensive service instantiated eagerly on every request even when not used; DI container initialising all services unconditionally
Auto-detectable: ✗ No blackfire symfony-profiler
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: Medium Context: Class Tests: Update

✓ schema.org compliant