DEV Community

Cover image for Open/Closed Principle (OCP) in php
Ahmed Raza Idrisi
Ahmed Raza Idrisi

Posted on

Open/Closed Principle (OCP) in php

Definition:

OCP states: "Software entities (classes, modules, functions) should be open for extension but closed for modification."

  • That means:

Open for extension: You can add new behavior without touching the existing code.

Closed for modification: You don't edit existing tested, stable code just to add new features.

  • Why this matters:

Prevents breaking existing features.

Improves maintainability.

Reduces regression bugs.

  • How to achieve it:

Interfaces / Abstract Classes — define a contract that new implementations follow.

Polymorphism — lets you swap behaviors without changing the base code.

Dependency Injection — avoids hardcoding dependencies.

  • Example (Bad OCP):
class ReportGenerator {
    public function generate($type) {
        if ($type === 'pdf') {
            // PDF generation logic
        } elseif ($type === 'csv') {
            // CSV generation logic
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

If we want to add Excel, we must edit ReportGenerator — violating OCP.

Better OCP-compliant design:

  • We use:
  1. Interface for report formats.
  2. Separate classes for each format.
  3. ReportGenerator doesn't know about specific formats — it just calls the interface.
  • Code Example:
interface ReportFormat {
    public function generate(array $data): string;
}

class PdfReport implements ReportFormat {
    public function generate(array $data): string {
        return "PDF Report generated with " . count($data) . " records.";
    }
}

class CsvReport implements ReportFormat {
    public function generate(array $data): string {
        return "CSV Report generated with " . count($data) . " records.";
    }
}

class ReportGenerator {
    private ReportFormat $format;

    public function __construct(ReportFormat $format) {
        $this->format = $format;
    }

    public function generateReport(array $data): string {
        return $this->format->generate($data);
    }
}

Enter fullscreen mode Exit fullscreen mode
$data = ['name' => 'John', 'age' => 30];

// Generate PDF
$pdfGenerator = new ReportGenerator(new PdfReport());
echo $pdfGenerator->generateReport($data);

// Generate CSV
$csvGenerator = new ReportGenerator(new CsvReport());
echo $csvGenerator->generateReport($data);

Enter fullscreen mode Exit fullscreen mode

Adding a new format (Excel):

class ExcelReport implements ReportFormat {
    public function generate(array $data): string {
        return "Excel Report generated with " . count($data) . " records.";
    }
}

Enter fullscreen mode Exit fullscreen mode

No change to ReportGenerator is needed — OCP respected ✅.

Top comments (0)