Fauzi Fadhlurrohman
6 min readFeb 23, 2023

How to implement better code even using PHP

We know that the development of technology today is very fast. Various programming languages have emerged with their own advantages. This makes the previous programming languages seem obsolete, one of which is the PHP programming language.
PHP is one of the programming languages that became popular in the early 2000s. Until now, there are still many programmers who use PHP. But some people think PHP is outdated.
Whereas in the programming concept taught by Uncle Bob, good code is not from the language but from how the code is designed to be easy to maintain. This concept is called the Clean Code concept. In implementing clean code we must understand 5 principles, namely SOLID.

PHP

Solid principles, also known as SOLID, are a set of software design principles that aim to create more maintainable, extensible, and scalable code. These principles can be applied to any programming language, including PHP, and are essential for any developer who wants to write high-quality code.

The SOLID principles are:

  1. Single Responsibility Principle (SRP)
  2. Open-Closed Principle (OCP)
  3. Liskov Substitution Principle (LSP)
  4. Interface Segregation Principle (ISP)
  5. Dependency Inversion Principle (DIP)

Let’s explore each of these principles in more detail and see how they can be applied in PHP.

  1. Single Responsibility Principle (SRP)

Single Responsibility Principle (SRP) The SRP states that a class should have only one responsibility. In other words, a class should have only one reason to change. If a class has more than one responsibility, it becomes harder to maintain and modify.

Example in PHP:

class User {
private $db;

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

public function create($data) {
// validation code
// save user to database
}

public function delete($id) {
// delete user from database
}

public function sendEmail($message) {
// send email to user
}
}

In this example, the User class has multiple responsibilities: creating users, deleting users, and sending emails. To apply the SRP, we could split the responsibilities into separate classes: User and EmailSender.

class User {
private $db;

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

public function create($data) {
// validation code
// save user to database
}

public function delete($id) {
// delete user from database
}
}
class EmailSender {
private $db;

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

public function sendEmail($user, $message) {
// send email to user
}
}

2. Open-Closed Principle (OCP)

Open-Closed Principle (OCP) The OCP states that a class should be open for extension but closed for modification. This means that we should be able to add new functionality to a class without changing its existing code.

Example in PHP:

interface PaymentInterface {
public function pay();
}
class Paypal implements PaymentInterface {
public function pay() {
// paypal payment code
}
}

class Stripe implements PaymentInterface {
public function pay() {
// stripe payment code
}
}

class PaymentProcessor {
private $paymentMethod;

public function __construct(PaymentInterface $paymentMethod) {
$this->paymentMethod = $paymentMethod;
}

public function process() {
// payment processing code
$this->paymentMethod->pay();
}
}

In this example, the PaymentProcessor class is open for extension because we can add new payment methods by creating new classes that implement the PaymentInterface. The PaymentProcessor class is closed for modification because we don't need to change its code to add new payment methods.

3. Liskov Subtitution Principle (LSP)

Liskov Substitution Principle (LSP) The LSP states that objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. In other words, a subclass should behave like its superclass.

Example in PHP:

class Animal {
public function makeSound() {
// make animal sound
}
}
class Cat extends Animal {
public function makeSound() {
// make cat sound
}
}

class Dog extends Animal {
public function makeSound() {
// make dog sound
}
}

function makeAnimalSound(Animal $animal) {
$animal->makeSound();
}

makeAnimalSound(new Cat()); // outputs cat sound
makeAnimalSound(new Dog()); // outputs dog sound

In this example, the Cat and Dog classes are subclasses of the Animal class. The makeAnimalSound function takes an Animal object as a parameter, which can be either a Cat or `Dog

object. Because the Cat and Dog classes override the makeSound method, they behave like their superclass Animal. Therefore, the makeAnimalSound function can be used with any Animal object without affecting the correctness of the program.

4. Interface Segregation Principle (ISP)

Interface Segregation Principle (ISP) The ISP states that a client should not be forced to depend on methods it does not use. In other words, we should separate the interface into smaller and more specific interfaces, so clients can depend only on the methods they need.

Example in PHP:

interface PaymentInterface {
public function pay();
public function refund();
public function void();
}
class Paypal implements PaymentInterface {
public function pay() {
// paypal payment code
}

public function refund() {
// paypal refund code
}

public function void() {
// paypal void code
}
}

class Stripe implements PaymentInterface {
public function pay() {
// stripe payment code
}

public function refund() {
// stripe refund code
}

public function void() {
// stripe void code
}
}

interface PaymentProcessorInterface {
public function processPayment(PaymentInterface $paymentMethod);
}

class PaymentProcessor implements PaymentProcessorInterface {
public function processPayment(PaymentInterface $paymentMethod) {
// payment processing code
$paymentMethod->pay();
}
}

In this example, the PaymentInterface has three methods: pay, refund, and void. However, the PaymentProcessor class only needs the pay method to process a payment. To apply the ISP, we can split the PaymentInterface into smaller interfaces, such as Payable, Refundable, and Voidable, and have the Paypal and Stripe classes implement only the interfaces they need. The PaymentProcessor class can then depend on the Payable interface instead of the PaymentInterface.

5. Depedency Inversion Principle (DIP)

Dependency Inversion Principle (DIP) The DIP states that high-level modules should not depend on low-level modules, but both should depend on abstractions. In other words, we should depend on interfaces or abstract classes instead of concrete classes.

Example in PHP:

interface LoggerInterface {
public function log($message);
}
class FileLogger implements LoggerInterface {
public function log($message) {
// log message to file
}
}

class DatabaseLogger implements LoggerInterface {
public function log($message) {
// log message to database
}
}

class User {
private $logger;

public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}

public function create($data) {
// validation code
// save user to database
$this->logger->log('User created');
}

public function delete($id) {
// delete user from database
$this->logger->log('User deleted');
}
}

$user = new User(new FileLogger());
$user->create($data);
$user->delete($id);

In this example, the User class depends on the LoggerInterface instead of concrete classes such as FileLogger or DatabaseLogger. This makes the User class more flexible because we can use any class that implements the LoggerInterface. We can also easily switch between different loggers without changing the User class code.

In conclusion, learning and applying SOLID principles in PHP programming can lead to more maintainable, extensible, and scalable code. These principles help us write code that is easier to understand, test, and modify, and also reduce the risk of introducing bugs or breaking changes in the future. By following these principles, we can write better quality software that meets the needs of our clients and users.

Here are some additional tips for applying SOLID principles in PHP programming:

  • Use dependency injection to inject dependencies into classes instead of creating them inside the class.
  • Use interfaces or abstract classes to define contracts that classes should adhere to.
  • Favor composition over inheritance when designing class hierarchies.
  • Use single responsibility principle to make classes and methods small and focused.
  • Use open-closed principle to make your code extensible by allowing new features to be added without modifying existing code.

By following these tips and applying SOLID principles, you can write PHP code that is more maintainable, testable, and scalable. Remember that SOLID principles are not a set of rules to follow blindly, but rather guidelines to help you write better code. It is important to understand the principles and apply them in a way that makes sense for your specific situation.

Fauzi Fadhlurrohman
Fauzi Fadhlurrohman

Written by Fauzi Fadhlurrohman

Hello there! I'm Fauzi Fadhlurrohman, a seasoned software engineer with a passion for crafting seamless digital experiences.

Responses (1)