Clean Architecture in PHP: A Comprehensive Guide

Explore Clean Architecture in PHP, focusing on separation of concerns, layer responsibilities, and dependencies for maintainable and testable applications.

8.8 Clean Architecture

Clean Architecture is a software design philosophy that emphasizes the separation of concerns, ensuring that each layer of an application has clear responsibilities and dependencies. This approach is particularly beneficial for PHP applications that require high maintainability and testability. In this section, we will delve into the principles of Clean Architecture, demonstrate how to implement it in PHP, and provide practical examples to solidify your understanding.

Intent of Clean Architecture

The primary intent of Clean Architecture is to create systems that are:

  • Independent of Frameworks: The architecture does not depend on the existence of some library of feature-laden software. This allows you to use such frameworks as tools, rather than having your system built around them.
  • Testable: The business rules can be tested without the user interface, database, web server, or any other external element.
  • Independent of UI: The UI can change easily, without changing the rest of the system. A web UI could be replaced with a console UI, for example, without changing the business rules.
  • Independent of Database: You can swap out Oracle or SQL Server for MongoDB, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
  • Independent of any external agency: In fact, your business rules simply don’t know anything at all about the outside world.

Implementing Clean Architecture in PHP

Implementing Clean Architecture in PHP involves organizing your code into distinct layers, each with specific responsibilities. The typical layers include:

  1. Entities: These are the business objects of the application. They encapsulate the most general and high-level rules. An entity can be an object with methods, or it can be a set of data structures and functions.

  2. Use Cases: This layer contains application-specific business rules. It orchestrates the flow of data to and from the entities, and it directs those entities to use their enterprise-wide business rules to achieve the goals of the use case.

  3. Interface Adapters: This layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web.

  4. Frameworks and Drivers: This is where all the details go. The web is a detail. The database is a detail. We keep these things on the outside where they can do little harm.

Dividing Code into Layers

Let’s explore how to divide your PHP code into these layers:

  • Entities Layer:
    • Define your core business logic and rules.
    • Ensure that this layer is independent of any other layer.
 1<?php
 2
 3class User {
 4    private $id;
 5    private $name;
 6    private $email;
 7
 8    public function __construct($id, $name, $email) {
 9        $this->id = $id;
10        $this->name = $name;
11        $this->email = $email;
12    }
13
14    public function changeEmail($newEmail) {
15        // Business rule: Email must be valid
16        if (!filter_var($newEmail, FILTER_VALIDATE_EMAIL)) {
17            throw new InvalidArgumentException("Invalid email address.");
18        }
19        $this->email = $newEmail;
20    }
21
22    // Other business logic methods...
23}
  • Use Cases Layer:
    • Implement application-specific logic.
    • Orchestrate interactions between entities.
 1<?php
 2
 3class ChangeUserEmail {
 4    private $userRepository;
 5
 6    public function __construct(UserRepository $userRepository) {
 7        $this->userRepository = $userRepository;
 8    }
 9
10    public function execute($userId, $newEmail) {
11        $user = $this->userRepository->findById($userId);
12        $user->changeEmail($newEmail);
13        $this->userRepository->save($user);
14    }
15}
  • Interface Adapters Layer:
    • Convert data formats between use cases and external systems.
 1<?php
 2
 3class UserController {
 4    private $changeUserEmail;
 5
 6    public function __construct(ChangeUserEmail $changeUserEmail) {
 7        $this->changeUserEmail = $changeUserEmail;
 8    }
 9
10    public function changeEmailAction($request) {
11        $userId = $request->get('user_id');
12        $newEmail = $request->get('new_email');
13        $this->changeUserEmail->execute($userId, $newEmail);
14        // Return response to the client
15    }
16}
  • Frameworks and Drivers Layer:
    • Handle framework-specific code and external dependencies.
 1<?php
 2
 3class MySQLUserRepository implements UserRepository {
 4    public function findById($userId) {
 5        // Fetch user from MySQL database
 6    }
 7
 8    public function save(User $user) {
 9        // Save user to MySQL database
10    }
11}

Ensuring Core Logic Independence

One of the key principles of Clean Architecture is ensuring that your core logic is not dependent on external layers. This is achieved by:

  • Dependency Inversion: High-level modules should not depend on low-level modules. Both should depend on abstractions.
  • Interfaces: Use interfaces to define contracts between layers, allowing for flexibility and decoupling.

Use Cases and Examples

Clean Architecture is particularly useful in applications that require high maintainability and testability. Here are some scenarios where Clean Architecture can be beneficial:

  • Enterprise Applications: Large-scale applications with complex business rules.
  • Microservices: Applications that need to be easily scalable and maintainable.
  • Test-Driven Development (TDD): Applications where testing is a priority.

Example: Building a Blog Platform

Let’s consider a simple blog platform to illustrate Clean Architecture in PHP.

  • Entities: Define the core business logic for posts and comments.
 1<?php
 2
 3class Post {
 4    private $id;
 5    private $title;
 6    private $content;
 7    private $comments = [];
 8
 9    public function __construct($id, $title, $content) {
10        $this->id = $id;
11        $this->title = $title;
12        $this->content = $content;
13    }
14
15    public function addComment(Comment $comment) {
16        $this->comments[] = $comment;
17    }
18
19    // Other business logic methods...
20}
  • Use Cases: Implement application-specific logic for managing posts and comments.
 1<?php
 2
 3class CreatePost {
 4    private $postRepository;
 5
 6    public function __construct(PostRepository $postRepository) {
 7        $this->postRepository = $postRepository;
 8    }
 9
10    public function execute($title, $content) {
11        $post = new Post(null, $title, $content);
12        $this->postRepository->save($post);
13    }
14}
  • Interface Adapters: Convert data formats between use cases and external systems.
 1<?php
 2
 3class PostController {
 4    private $createPost;
 5
 6    public function __construct(CreatePost $createPost) {
 7        $this->createPost = $createPost;
 8    }
 9
10    public function createAction($request) {
11        $title = $request->get('title');
12        $content = $request->get('content');
13        $this->createPost->execute($title, $content);
14        // Return response to the client
15    }
16}
  • Frameworks and Drivers: Handle framework-specific code and external dependencies.
1<?php
2
3class MySQLPostRepository implements PostRepository {
4    public function save(Post $post) {
5        // Save post to MySQL database
6    }
7}

Visualizing Clean Architecture

To better understand the structure of Clean Architecture, let’s visualize it using a diagram. This diagram represents the layers and their dependencies.

    graph TD;
	    A["Entities"] -->|Use Cases| B["Use Cases"];
	    B -->|Interface Adapters| C["Interface Adapters"];
	    C -->|Frameworks & Drivers| D["Frameworks & Drivers"];
	    D -->|External Systems| E["External Systems"];

Diagram Description: This diagram illustrates the flow of dependencies in Clean Architecture. The core entities are at the center, surrounded by use cases, interface adapters, and finally, frameworks and drivers. External systems interact with the outermost layer.

PHP Unique Features

PHP offers several unique features that can enhance the implementation of Clean Architecture:

  • Traits: Use traits to share methods across classes without inheritance.
  • Anonymous Classes: Create lightweight, one-off classes for specific tasks.
  • Namespaces: Organize code into logical groups, avoiding naming conflicts.
  • Composer: Manage dependencies and autoload classes efficiently.

Design Considerations

When implementing Clean Architecture in PHP, consider the following:

  • Complexity: Clean Architecture can introduce complexity with multiple layers. Ensure that the benefits outweigh the complexity for your specific application.
  • Performance: While Clean Architecture promotes separation of concerns, it may introduce performance overhead. Optimize critical paths and use caching where necessary.
  • Flexibility: Clean Architecture provides flexibility in swapping out components. Ensure that interfaces are well-defined and stable.

Differences and Similarities

Clean Architecture is often compared to other architectural patterns, such as:

  • Layered Architecture: Both emphasize separation of concerns, but Clean Architecture focuses more on dependency inversion.
  • Hexagonal Architecture: Similar in promoting independence from external systems, but with different terminology and focus areas.

Try It Yourself

To solidify your understanding of Clean Architecture, try modifying the code examples provided:

  • Add a new feature: Implement a feature to delete a post, ensuring that it follows the principles of Clean Architecture.
  • Swap out a component: Replace the MySQL repository with a different database, such as MongoDB, and observe how the architecture supports this change.

Knowledge Check

  • Question: What is the primary intent of Clean Architecture?
  • Exercise: Implement a simple to-do list application using Clean Architecture principles.

Embrace the Journey

Remember, Clean Architecture is a journey, not a destination. As you continue to develop PHP applications, keep experimenting with different architectural patterns, stay curious, and enjoy the process of creating maintainable and testable software.

Quiz: Clean Architecture

Loading quiz…
Revised on Thursday, April 23, 2026