Backend Development 8 min read

Applying SOLID Principles in PHP for Maintainable Code

This article explains how to use the SOLID design principles—SRP, OCP, LSP, ISP, and DIP—in PHP, providing clear bad and good code examples for each principle to help developers write more reliable, extensible, and maintainable backend applications.

php中文网 Courses
php中文网 Courses
php中文网 Courses
Applying SOLID Principles in PHP for Maintainable Code

Reliable, maintainable code is the cornerstone of any successful PHP project. To achieve this, we can follow the SOLID principles when writing code. These principles include Single Responsibility Principle (SRP), Open/Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP) and Dependency Inversion Principle (DIP).

Single Responsibility Principle (SRP).

The Single Responsibility Principle states that a class should have only one reason to change. In PHP this means a class should have a single responsibility. Such design improves code maintainability and readability.

Bad Example – Mixed Responsibilities

<code>class  User<br/> { <br/>    public  function  verify ( $username , $password ) { /* ... */ } <br/>    public  function  sendEmail ( $message ) { /* ... */ } <br/>} <br/></code>

Good Example – Single Responsibility

<code>class  UserAuthenticator<br/> { <br/>    public  function  verify ( $username , $password ) { /* ... */ } <br/>} <br/>class EmailSender<br/> {<br/>     public  function  sendEmail ( $message ) { /* ... */ }<br/>}<br/></code>

Open/Closed Principle (OCP).

The Open/Closed Principle states that classes should be open for extension but closed for modification. In PHP we can use interfaces and abstract classes to implement this principle. By defining interfaces and abstract classes, we can extend functionality without modifying existing code.

Bad Example – Direct Modification

<code>class Square<br/>{<br/>    public $side;<br/>    public function __construct($side)<br/>    {<br/>        $this->side = $side;<br/>    }<br/>}<br/>class AreaCalculator<br/>{<br/>    public function calculate($shapes)<br/>    {<br/>        $area = 0;<br/>        foreach ($shapes as $shape) {<br/>            if ($shape instanceof Square) {<br/>                $area += $shape->side * $shape->side;<br/>            } elseif ($shape instanceof Circle) {<br/>                $area += pi() * $shape->radius * $shape->radius;<br/>            }<br/>        }<br/>        return $area;<br/>    }<br/>}<br/></code>

Good Example – Open for Extension

<code>interface Shape<br/>{<br/>    public function area();<br/>}<br/>class Square implements Shape<br/>{<br/>    private $side;<br/>    public function __construct($side)<br/>    {<br/>        $this->side = $side;<br/>    }<br/>    public function area()<br/>    {<br/>        return $this->side * $this->side;<br/>    }<br/>}<br/>class Circle implements Shape<br/>{<br/>    private $radius;<br/>    public function __construct($radius)<br/>    {<br/>        $this->radius = $radius;<br/>    }<br/>    public function area()<br/>    {<br/>        return pi() * $this->radius * $this->radius;<br/>    }<br/>}<br/></code>

Liskov Substitution Principle (LSP)

The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of a subclass without affecting program correctness. In PHP, adhering to this principle ensures derived classes maintain the contract of their base class, guaranteeing code consistency and reliability.

Bad Example – Violating LSP

<code>class Bird<br/>{<br/>    public function fly() { /* ... */ }<br/>}<br/><br/>class Ostrich extends Bird<br/>{<br/>    public function fly() { throw new Exception("Ostrich cannot fly"); }<br/>}<br/></code>

Good Example – Following LSP

<code>interface Bird<br/>{<br/>    public function fly();<br/>}<br/>class Sparrow implements Bird<br/>{<br/>    public function fly() { /* ... */ }<br/>}<br/>class Ostrich implements Bird<br/>{<br/>    public function fly() { /* ... */ }<br/>}<br/></code>

Interface Segregation Principle (ISP)

The Interface Segregation Principle states that clients should not be forced to depend on interfaces they do not use. In PHP this means creating smaller, more focused interfaces rather than large, monolithic ones. This design improves code flexibility and maintainability.

Bad Example – Interface Bloat

<code>interface Worker<br/>{<br/>    public function work();<br/>    public function eat();<br/>    public function sleep();<br/>}<br/></code>

Good Example – Interface Segregation

<code>interface Workable<br/>{<br/>    public function work();<br/>}<br/>interface Eatable<br/>{<br/>    public function eat();<br/>}<br/>interface Sleepable<br/>{<br/>    public function sleep();<br/>}<br/></code>

Dependency Inversion Principle (DIP)

The Dependency Inversion Principle states that high-level modules should not depend on low-level modules; both should depend on abstractions. In PHP we can use dependency injection and abstractions to decouple classes. This improves testability and maintainability.

Bad Example – High-level module depends on low-level module

<code>class LightBulb<br/>{<br/>    public function turnOn() { /* ... */ }<br/>    public function turnOff() { /* ... */ }<br/>}<br/><br/>class Switch<br/>{<br/>    private $bulb;<br/>    public function __construct()<br/>    {<br/>        $this->bulb = new LightBulb();<br/>    }<br/>    public function operate()<br/>    {<br/>        // Operate the bulb<br/>    }<br/>}<br/></code>

Good Example – Abstraction and Dependency Injection

<code>interface Switchable<br/>{<br/>    public function turnOn();<br/>    public function turnOff();<br/>}<br/>class LightBulb implements Switchable<br/>{<br/>    public function turnOn() { /* ... */ }<br/>    public function turnOff() { /* ... */ }<br/>}<br/>class Switch<br/>{<br/>    private $device;<br/>    public function __construct(Switchable $device)<br/>    {<br/>        $this->device = $device;<br/>    }<br/>    public function operate()<br/>    {<br/>        // Operate the device<br/>    }<br/>}<br/></code>

In summary, writing PHP code that follows SOLID principles is essential for creating maintainable and extensible applications. By adhering to these principles and implementing the provided examples, you can ensure your PHP code becomes more robust, flexible, and easier to maintain over time. Remember that applying these principles may require a shift in mindset and design, but the benefits to code quality and maintainability are worth the effort. Happy coding!

backendcode qualityPHPdesign principlesSOLID
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.