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

Law of Demeter — PHP Examples

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

Closest to 'only careful code review or runtime testing' (d7). The detection_hints list phpmd and phpstan, but automated detection is explicitly marked 'no' — these tools can flag syntactic method chains but cannot reliably distinguish LoD violations (crossing object boundaries) from legitimate fluent interfaces on a single object. Human code review is required to make that judgment, placing this firmly at d7.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes adding delegation methods (e.g., $order->getCustomerEmail()), which sounds like a local fix, but the common_mistakes note that simply adding getters to intermediates shifts not removes coupling, and the 'extended' analysis reveals systemic coupling patterns across many methods. Properly fixing LoD violations typically means restructuring how multiple collaborators communicate, touching several classes and possibly DTOs, putting this at e5.

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

Closest to 'persistent productivity tax' (b5). The term applies_to web, cli, and queue-worker — essentially the full PHP codebase scope. The 'extended' framing explicitly notes that systemic LoD violations are a coordination smell requiring structural change. Once coupling is baked in across many object traversals, every future change must navigate or work around those chains, imposing a persistent productivity tax, but it does not fully define the system's shape (not b7).

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 explicitly states the canonical wrong belief: that all method chaining is a LoD violation. Fluent interfaces on a single object are fine; the violation is navigating through multiple distinct objects. This is a well-known, documented gotcha that many developers get wrong initially (especially confusing builder/fluent patterns with train-wreck chains), placing this at t5.

About DEBT scoring →

Also Known As

LoD extended train wreck method chain smell

TL;DR

The Law of Demeter (don't talk to strangers) limits method chains — each unit should call only its direct collaborators, not traverse object graphs.

Explanation

The Law of Demeter (LoD) states a method should only call methods on: itself, its parameters, objects it creates, and its direct fields. Chained calls like $order->getCustomer()->getAddress()->getCity()->getName() violate LoD — the method knows the entire object graph structure, creating hidden coupling. Every link in the chain is a dependency on internal structure that can break silently. The fix is Tell Don't Ask: add $order->getCustomerCity() that encapsulates the traversal. This is not a rigid rule against all fluent interfaces (builders, query builders designed for chaining are fine) but a smell detector for domain traversal chains. In PHP, long chains frequently appear in controller code accessing nested relationships — these belong in dedicated query methods or read models.

Common Misconception

Chaining methods is always a Law of Demeter violation. Fluent interfaces on a single object are fine — the violation is navigating through multiple distinct objects to reach data, exposing intermediate structure the caller should not know about.

Why It Matters

Extended LoD analysis reveals systemic coupling patterns that single-method analysis misses — if a class consistently violates LoD across many methods, it is a coordination smell requiring structural change.

Common Mistakes

  • Treating LoD violations as purely style issues — they are structural coupling that compounds over time.
  • Using the Tell, Don't Ask principle only at the micro level without applying it to system design.
  • Fixing LoD violations by adding getters to intermediate objects — this shifts not removes the coupling.
  • Not using data transfer objects to carry information across boundaries rather than reaching through object graphs.

Code Examples

✗ Vulnerable
// Violates LoD — knows entire object graph
$city = $order->getCustomer()->getAddress()->getCity()->getName();
✓ Fixed
// Order encapsulates the traversal
$city = $order->getCustomerCity();

Added 15 Mar 2026
Edited 22 Mar 2026
Views 92
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings S 0 pings M 0 pings T 2 pings W 2 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M
No pings yet today
No pings yesterday
Amazonbot 9 Ahrefs 7 Google 7 PetalBot 6 Scrapy 5 SEMrush 5 Bing 4 Unknown AI 3 Brave Search 3 Majestic 2 Perplexity 2 Applebot 2 Meta AI 1 Twitter/X 1
crawler 54 crawler_json 2 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Add delegation methods to bridge the gap — if callers always do $order->getCustomer()->getEmail(), add $order->getCustomerEmail() and let Order handle the traversal internally
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
$a->getB()->getC()->doSomething() three or more chained getters crossing object boundaries; callers knowing internal structure of collaborators
Auto-detectable: ✗ No phpmd phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: High Context: Class Tests: Update


✓ schema.org compliant