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

Composite Pattern

quality Intermediate
debt(d5/e5/b5/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5). PHPStan can detect type inconsistencies and missing interface implementations, but detecting inappropriate composite pattern usage (isinstance checks handling leaves vs composites differently, lack of uniform interface) requires static analysis rules or careful code review. The detection_hints indicate automated detection is 'no', suggesting beyond simple linting.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix suggests implementing a Component interface with Leaf and Composite classes — this requires creating or modifying multiple classes, updating client code to use the uniform interface, and potentially restructuring existing hierarchies. Not a one-line fix, but contained within a single architectural concern.

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

Closest to 'persistent productivity tax' (b5). The pattern applies across web/cli/queue-worker contexts and once adopted for a hierarchy (file systems, UI components, permissions), it shapes how all code interacts with that structure. However, it's typically localized to specific subsystems rather than defining the entire system's architecture, placing it at moderate reach/burden.

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

Closest to 'notable trap' (t5). The misconception explicitly states developers wrongly believe 'composite pattern is only useful for tree data structures' when it applies broadly to uniform treatment of objects and collections. Additionally, common_mistakes cite parent reference memory leaks and failing to implement uniform interfaces — documented gotchas that most developers eventually learn but aren't immediately obvious.

About DEBT scoring →

Also Known As

composite design pattern tree structure pattern

TL;DR

Treats individual objects and compositions of objects uniformly through a shared interface, enabling tree-structured hierarchies.

Explanation

The Composite pattern composes objects into tree structures to represent part-whole hierarchies. Both leaf objects and composites implement the same Component interface, so client code treats them identically — calling render() on a single widget or a container of widgets uses the same API. In PHP, this appears in menu systems, file system trees, expression parsers, and UI component hierarchies. The key benefit is that client code doesn't need to distinguish between individual items and collections. The trade-off is that it can make it too easy to build overly general designs.

Common Misconception

The composite pattern is only useful for tree data structures. It is useful anywhere you want clients to treat individual objects and collections of objects uniformly — file systems, UI component trees, permission hierarchies, and expression parsers all benefit.

Why It Matters

The Composite pattern lets clients treat individual objects and compositions uniformly — a tree of nodes where leaves and branches share the same interface eliminates special-casing in client code.

Common Mistakes

  • Adding parent references to nodes without managing them — circular references cause memory leaks in PHP.
  • Not making leaf nodes and composite nodes implement the same interface — forces type-checking in the client.
  • Using Composite when the hierarchy is fixed and shallow — a simple array or collection is sufficient.
  • Exposing the children collection directly — encapsulate add/remove to maintain invariants.

Code Examples

✗ Vulnerable
// Type-checking instead of uniform interface:
function renderMenu(mixed $item): string {
    if ($item instanceof MenuItem) return $item->render();
    if ($item instanceof MenuGroup) { // Separate handling — use Composite
        return implode('', array_map(fn($i) => renderMenu($i), $item->items));
    }
}
✓ Fixed
// Treat individual objects and compositions uniformly
interface HtmlElement {
    public function render(): string;
}

class TextNode implements HtmlElement {
    public function __construct(private string \$text) {}
    public function render(): string { return htmlspecialchars(\$this->text); }
}

class HtmlTag implements HtmlElement {
    private array \$children = [];
    public function __construct(private string \$tag) {}
    public function add(HtmlElement \$e): void { \$this->children[] = \$e; }
    public function render(): string {
        \$inner = implode('', array_map(fn(\$c) => \$c->render(), \$this->children));
        return "<{\$this->tag}>{\$inner}</{\$this->tag}>";
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 31
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 3 pings 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 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 0 pings W 0 pings T 2 pings F
Amazonbot 1 Ahrefs 1
No pings yesterday
Amazonbot 9 Ahrefs 7 Perplexity 5 Google 2 Unknown AI 2 ChatGPT 2 Bing 1
crawler 26 crawler_json 2
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Implement a Component interface with an operation() method — Leaf implements it directly, Composite stores children and iterates them on operation() — clients treat both identically
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
isinstance checks to handle leaves vs composites differently; tree structure without uniform interface; category hierarchy without recursive traversal
Auto-detectable: ✗ No phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update

✓ schema.org compliant