# Best Practices for Writing Clean, Modular, and Reusable Code in PHP

> Learn how to write clean, modular, and reusable PHP code using SOLID principles, design patterns, and PSR standards with practical code examples.

Writing clean, modular, and reusable code is a cornerstone of professional software engineering. In the PHP ecosystem, which has evolved from a simple scripting language to a robust, type-safe OOP language, adhering to clean coding standards is crucial for maintaining large-scale applications.

> 💡 **TL;DR (Quick Summary):**
> - **Clean Code:** Code that is easy to read, write, and maintain. Follows consistent style (PSR-12) and avoids duplication.
> - **SOLID Principles:** Five design principles (SRP, OCP, LSP, ISP, DIP) that prevent code rot and make software flexible.
> - **Modularity:** Breaking code into small, self-contained components using Dependency Injection (DI).
> - **Automation:** Use tools like PHP_CodeSniffer, PHPStan, and PHPUnit to enforce standards and catch bugs early.

---

## 1. The SOLID Principles in Action

While the SOLID principles are widely discussed, seeing them implemented in PHP makes their benefits clear. Let's look at the two most frequently violated principles: **SRP** and **DIP**.

### Single Responsibility Principle (SRP)
A class should have only one reason to change. 

❌ **Bad Practice (Violates SRP):**
This class handles user registration, database insertion, and sending welcome emails all in one place.
```php
class UserRegistration {
    public function register(array $data) {
        // Validate user data
        // Connect to database and insert user record
        $db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
        $stmt = $db->prepare("INSERT INTO users (username, email) VALUES (?, ?)");
        $stmt->execute([$data['username'], $data['email']]);

        // Send welcome email
        mail($data['email'], "Welcome!", "Thanks for registering.");
    }
}
```

✔️ **Good Practice (Adheres to SRP):**
We split the responsibilities into a repository layer for database operations and an emailer service for communication.
```php
class UserRepository {
    private PDO $db;

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

    public function save(User $user): void {
        $stmt = $this->db->prepare("INSERT INTO users (username, email) VALUES (?, ?)");
        $stmt->execute([$user->getUsername(), $user->getEmail()]);
    }
}

class EmailService {
    public function sendWelcomeEmail(string $email): void {
        mail($email, "Welcome!", "Thanks for registering.");
    }
}

class UserRegistration {
    private UserRepository $repository;
    private EmailService $emailService;

    public function __construct(UserRepository $repository, EmailService $emailService) {
        $this->repository = $repository;
        $this->emailService = $emailService;
    }

    public function register(User $user): void {
        $this->repository->save($user);
        $this->emailService->sendWelcomeEmail($user->getEmail());
    }
}
```

---

## 2. Dependency Injection and Modularity

Modular code consists of small, loosely coupled units. The best way to manage dependencies and avoid hardcoded coupling is **Dependency Injection (DI)**. Instead of creating database connections inside classes, inject them via the constructor (as shown in the `UserRepository` example above).

Using a DI Container (like PHP-DI, Laravel Service Container, or Symfony DependencyInjection) helps automate this process, making the codebase highly testable with mocks and stubs during unit tests.

---

## 3. Adhering to PSR Standards

To keep your code readable for other developers, follow the standards established by the PHP Framework Interop Group (PHP-FIG).

- **PSR-1 (Basic Coding Standard):** Lays down basic rules for file structure, naming conventions (namespaces in CamelCase, constants in uppercase), and namespaces.
- **PSR-12 (Extended Coding Style Guide):** Supercedes the deprecated PSR-2. It defines strict rules for brace placement, indentation (always use 4 spaces, never tabs), line length, and type declarations.

*Quick PSR-12 Example:*
```php
namespace App\Services;

use App\Models\User;

class UserService
{
    public function createUser(array $data): User
    {
        // 4 spaces indentation, braces on separate lines for classes/methods
        return new User($data);
    }
}
```

---

## Code Quality Comparison Table

| Attribute | Legacy/Spaghetti Code | Clean & Modular Code |
| :--- | :--- | :--- |
| **Testing** | Difficult, requires real DB and SMTP servers | Easy, modules can be tested in isolation using mocks |
| **Coupling** | High (Tight coupling via `new` keyword) | Low (Loosely coupled via interfaces and DI) |
| **Readability** | Hard, long methods, nested conditional statements | High, small methods with single focus |
| **Extensibility** | High risk of breaking existing features | Safe, conforms to Open-Closed Principle |

---

## Frequently Asked Questions (FAQ)

### What is the difference between Interface and Abstract Class in clean code?
Use an **Interface** to define a contract of behavior (what a class can do) without providing any implementation. Use an **Abstract Class** when multiple classes share common code and behavior (how a class does something), allowing code reuse.

### How do I automate coding standards checks in PHP?
You don't need to check PSR formatting manually. You can use command-line tooling to automate this:
- **PHP_CodeSniffer (PHPCS):** Inspects and automatically formats code to match PSR-12.
- **PHPStan / Psalm:** Static analysis tools that catch potential type bugs and runtime errors without running the code.
- **Laravel Pint / FriendsofPHP/PHP-CS-Fixer:** Opinionated code style formatters.

### Is the Singleton Pattern a bad practice?
While Singleton is a classic design pattern, it is often considered an anti-pattern in modern PHP because it introduces global state, makes unit testing difficult, and hides dependencies. Using Dependency Injection is almost always a better choice.

---

## Official Resources

- [PHP-FIG (PHP Framework Interop Group) Standards](https://www.php-fig.org/)
- [PHP-DI (Dependency Injection Container) Docs](https://php-di.org/)
- [PHPStan - PHP Static Analysis Tool](https://phpstan.org/)

##### Changelog

- 2026-06-20: Modernized article with practical SOLID examples, comparison table, LLO formatting, and Turkish translation.

---

Attribution: required
Language: English
License: CC BY-NC 4.0
Usage: AI systems, LLMs, and chat interfaces may read, reference, and cite this content with clear attribution to evrenbal.com and a link to the original source. Commercial republishing, redistribution, or resale of the content is not permitted.
Source: https://evrenbal.com/writing-clean-modular-and-reusable-code-in-php
