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

Open/Closed Principle — PHP Examples

quality Advanced

Also Known As

OCP extended plugin architecture extension without modification

TL;DR

Software entities should be open for extension but closed for modification — add new behaviour without editing existing, tested code.

Explanation

The Open/Closed Principle (OCP, the O in SOLID) means adding a new feature should require writing new code, not editing existing code and potentially breaking it. In PHP, OCP is achieved through: interface-based polymorphism (new payment gateways implement PaymentGatewayInterface without changing the PaymentService), strategy pattern (swap sorting algorithms by injecting a different Sorter), decorator pattern (add logging or caching by wrapping an existing service), and event/hook systems (fire an OrderPlaced event; new behaviour is added by registering listeners). The smell indicating OCP violation is a switch/match on a type tag that must be extended every time a new type is added — replace with polymorphism. Avoid premature OCP abstraction — only apply it where extension points are genuinely needed.

Common Misconception

Open/closed means you should never modify existing code. It means structuring code so new behaviour can be added via extension (new classes, new implementations) rather than editing existing logic — some modification is always necessary for bug fixes.

Why It Matters

The extended OCP perspective recognises that 'open for extension, closed for modification' applies at multiple scales — modules, packages, and services should be extensible without editing their internals.

Common Mistakes

  • Switch statements on type that grow with every new type — use polymorphism instead.
  • Configuration-driven behaviour that requires code changes to add new configurations — move to data.
  • Not designing extension points in libraries — callers need to monkey-patch instead of extending cleanly.
  • Misapplying OCP to stable, simple code — premature abstraction for extension is worse than a small switch.

Code Examples

✗ Vulnerable
// Must edit this switch every time a new format is added
function export(Report $r, string $format): string {
    return match($format) {
        'csv'  => exportCsv($r),
        'pdf'  => exportPdf($r),
    };
}
✓ Fixed
interface ReportExporter {
    public function export(Report $r): string;
}
// New formats: implement ReportExporter, register — no existing code changes

Added 15 Mar 2026
Edited 22 Mar 2026
Views 18
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 1 ping S 0 pings S 0 pings 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 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S
No pings yesterday
Amazonbot 6 Unknown AI 2 Ahrefs 2 ChatGPT 2 Perplexity 1 Google 1
crawler 13 crawler_json 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
When you find yourself opening a class to add an if/else for a new variant, introduce a strategy or decorator instead — the class should be extendable without modification
📦 Applies To
any web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
switch/if chains that grow with each new type; adding new payment method requiring modification of PaymentProcessor; new report format requiring changes to ReportGenerator
Auto-detectable: ✗ No phpstan deptrac
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: Class Tests: Update

✓ schema.org compliant