Mastering PHP SOLID Principles with Real Code Examples

Learn how to implement SOLID principles in PHP with practical code examples to enhance your software design.

Mastering PHP SOLID Principles with Real Code Examples

Learn PHP SOLID principles with real examples. Build object‑oriented application design, maintenance, and testability for your backend‑first PHP code today.

In learning PHP SOLID principles, an incredible transformation will take place in the structure, readability, and maintainability of your code. These five principles are the origin of object‑oriented PHP as we know it today. We will look at SOLID concepts one by one and try to understand each through real‑life PHP examples, as applying these principles brings about cleaner backend systems that can be tested.

Mastering PHP SOLID Principles with Real Code Examples

SOLID principles are five design rules meant to guide developers in designing better object‑oriented software so that they are manageable and extensible. The alphabet S stands for:

S – Single Responsibility Principle (SRP)

One reason to change is enough. If it's responsible for both data storage and email notifications, it's doing too much.

Example (Violates SRP)


class User {
    public function save() {
        // save user to DB
    }

    public function sendWelcomeEmail() {
        // send email
    }
}
  

Refactored Version


class User {
    // user data model
}

class UserRepository {
    public function save(User $user) { /* ... */ }
}

class Mailer {
    public function sendWelcomeEmail(User $user) { /* ... */ }
}
  

O – Open/Closed Principle (OCP)

Example Using Strategy Pattern


interface PaymentMethod {
    public function pay(float $amount);
}

class CreditCard implements PaymentMethod {
    public function pay(float $amount) {
        // charge card
    }
}

class PayPal implements PaymentMethod {
    public function pay(float $amount) {
        // use PayPal API
    }
}

class Checkout {
    public function __construct(private PaymentMethod $method) {}

    public function processPayment(float $amount) {
        $this->method->pay($amount);
    }
}
  

L – Liskov Substitution Principle (LSP)

Subclass objects should be able to replace the parent class’s objects without altering program behaviour.

Bad Example


class Bird {
    public function fly() { /* ... */ }
}

class Ostrich extends Bird {
    public function fly() {
        throw new Exception("I can't fly!");
    }
}
  

Better Design


interface Bird {
    public function layEggs();
}

interface FlyingBird extends Bird {
    public function fly();
}
  

Now, only birds that can fly implement FlyingBird.

I – Interface Segregation Principle (ISP)

Large interfaces that try to be generic often lead to unnecessary implementations. Split them into focused interfaces.

Poor Interface Design


interface Worker {
    public function work();
    public function eat();
}
  

What if we have a robot? It doesn’t eat!

Improved Version


interface Workable {
    public function work();
}

interface Eatable {
    public function eat();
}
  

A robot would implement only Workable; humans could implement both.

D – Dependency Inversion Principle (DIP)

High‑level modules should not depend on low‑level modules. Both should depend on abstractions.

This principle promotes loose coupling between layers by relying on interfaces rather than concrete implementations.

Without DIP


class PasswordReminder {
    private $db;

    public function __construct() {
        $this->db = new MySQLConnection();
    }
}
  

PasswordReminder is tightly coupled to MySQLConnection.

With DIP


interface DBConnection {
    public function connect();
}

class MySQLConnection implements DBConnection {
    public function connect() { /* ... */ }
}

class PasswordReminder {
    public function __construct(private DBConnection $db) {}
}
  

The reminder now depends on an abstraction. You can swap databases easily and test with mocks.

Applying PHP SOLID Principles in Real‑World PHP Projects

Use SRP in Laravel Controllers

Avoid placing all logic in controllers. Extract logic to services or jobs.

Use OCP with Events and Listeners

Add functionality by attaching event listeners, without modifying core logic.

Use LSP for API Transformations

When transforming models to API responses, ensure subclasses behave consistently.

Use ISP for Service Interfaces

Instead of a massive UserServiceInterface, split it into:

Use DIP in Service Binding

In Laravel:


$this->app->bind(ReportGeneratorInterface::class, PDFReportGenerator::class);
  

That enables swapping implementations for different contexts.

Tools to Support PHP SOLID Principles Development

When to Be Flexible with PHP SOLID Principles

While SOLID offers great architectural guidance, you don’t have to enforce every rule rigidly all the time. A small class doesn’t always need a dozen interfaces.

Use SOLID when:

PHP SOLID Principles

If you grasp these SOLID concepts very well, you can turn object‑oriented PHP from something that just works into something great. A PHP developer should abstract, keep classes single‑purpose, and depend on interfaces to obtain code that is testable, extendable, and future‑ready.

Random 3 articles