Understanding SOLID Principles in PHP
Single Responsibility Principle (SRP)
A class should have only one reason to change.
// Bad
class User {
public function saveUser($data) { /* ... */ }
public function generateReport() { /* ... */ }
public function sendEmail() { /* ... */ }
}
// Good
class User {
public function save($data) { /* ... */ }
}
class UserReportGenerator {
public function generate() { /* ... */ }
}
class UserNotifier {
public function sendEmail() { /* ... */ }
}
Open/Closed Principle (OCP)
Software entities should be open for extension but closed for modification.
// Bad
class PaymentProcessor {
public function processPayment($type) {
if ($type === 'credit') {
// Process credit payment
} elseif ($type === 'debit') {
// Process debit payment
}
}
}
// Good
interface PaymentMethod {
public function processPayment();
}
class CreditPayment implements PaymentMethod {
public function processPayment() { /* ... */ }
}
class DebitPayment implements PaymentMethod {
public function processPayment() { /* ... */ }
}
Liskov Substitution Principle (LSP)
Subtypes must be substitutable for their base types.
// Bad
class Bird {
public function fly() { /* ... */ }
}
class Penguin extends Bird {
public function fly() {
throw new Exception("Cannot fly");
}
}
// Good
interface Flyable {
public function fly();
}
class Bird {
public function eat() { /* ... */ }
}
class Sparrow extends Bird implements Flyable {
public function fly() { /* ... */ }
}
class Penguin extends Bird {
public function swim() { /* ... */ }
}
Interface Segregation Principle (ISP)
Clients should not be forced to depend on interfaces they don't use.
// Bad
interface Worker {
public function work();
public function eat();
public function sleep();
}
// Good
interface Workable {
public function work();
}
interface Eatable {
public function eat();
}
interface Sleepable {
public function sleep();
}
class Human implements Workable, Eatable, Sleepable {
public function work() { /* ... */ }
public function eat() { /* ... */ }
public function sleep() { /* ... */ }
}
class Robot implements Workable {
public function work() { /* ... */ }
}
Dependency Inversion Principle (DIP)
High-level modules should not depend on low-level modules. Both should depend on abstractions.
// Bad
class UserService {
private MySQLDatabase $database;
public function __construct() {
$this->database = new MySQLDatabase();
}
}
// Good
interface DatabaseInterface {
public function query($sql);
}
class UserService {
private DatabaseInterface $database;
public function __construct(DatabaseInterface $database) {
$this->database = $database;
}
}
class MySQLDatabase implements DatabaseInterface {
public function query($sql) { /* ... */ }
}
class PostgreSQLDatabase implements DatabaseInterface {
public function query($sql) { /* ... */ }
}
These principles help create maintainable, flexible, and robust code. Following SOLID makes your code easier to test, modify, and extend over time.
Top comments (0)