Current Location: Home> Latest Articles> Exploring the Chain of Responsibility Pattern in PHP Object-Oriented Programming

Exploring the Chain of Responsibility Pattern in PHP Object-Oriented Programming

M66 2025-06-18

Exploring the Chain of Responsibility Pattern in PHP Object-Oriented Programming

The Chain of Responsibility pattern is a behavioral design pattern that allows a request to be passed along a chain of handlers until one of them is able to process the request. This enables decoupling between the different handlers, and the processing chain can be dynamically changed or extended by adding new handlers.

In PHP, using object-oriented programming (OOP) provides a better way to implement the Chain of Responsibility pattern. Below, we will demonstrate how to implement this pattern through a simple example code.

1. Create an Abstract Handler Class

First, we define an abstract class `Handler` as the base class for all concrete handlers. This class contains the method `handle()` to process requests and the method `setNext()` to set the next handler in the chain:

abstract class Handler {
    protected $nextHandler;

    public function setNext(Handler $handler) {
        $this->nextHandler = $handler;
    }

    abstract public function handle(Request $request);
}

2. Implement Concrete Handler Classes

Next, we create a concrete handler class that extends the `Handler` class and implements the `handle()` method. In the processing logic, if the current handler cannot process the request, it passes the request to the next handler:

class ConcreteHandler1 extends Handler {
    public function handle(Request $request) {
        if ($request->getType() == 'type1') {
            echo "Handled by ConcreteHandler1";
        } else {
            if ($this->nextHandler) {
                $this->nextHandler->handle($request);
            } else {
                echo "No handler can handle the request";
            }
        }
    }
}

3. Create Another Concrete Handler Class

We create another concrete handler class `ConcreteHandler2`, which handles different types of requests than `ConcreteHandler1`. We set it as the next handler for `ConcreteHandler1`:

class ConcreteHandler2 extends Handler {
    public function handle(Request $request) {
        if ($request->getType() == 'type2') {
            echo "Handled by ConcreteHandler2";
        } else {
            if ($this->nextHandler) {
                $this->nextHandler->handle($request);
            } else {
                echo "No handler can handle the request";
            }
        }
    }
}

4. Create the Request Class

To pass the request information to the handlers, we need a `Request` class that encapsulates the request data. It contains the type of the request to allow it to be passed between handlers:

class Request {
    protected $type;

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

    public function getType() {
        return $this->type;
    }
}

5. Test the Chain of Responsibility Pattern

Finally, we can test the implementation of the Chain of Responsibility pattern. First, we create a request object, then create two handler objects, and set them up in the processing chain. Next, we pass the request to the first handler to see how the processing occurs:

$request = new Request('type2');
$handler1 = new ConcreteHandler1();
$handler2 = new ConcreteHandler2();

$handler1->setNext($handler2);
$handler1->handle($request);

Running the above code will produce the following output:

Handled by ConcreteHandler2

From the test code, we can see that when the request type is 'type2', `ConcreteHandler2` is able to handle the request, so it outputs "Handled by ConcreteHandler2". When the request type is 'type1', `ConcreteHandler1` cannot handle it, so the request is passed to `ConcreteHandler2`. If there are no more handlers in the chain, it outputs "No handler can handle the request".

Conclusion

The Chain of Responsibility pattern provides a flexible way to handle requests in object-oriented programming. Each handler only cares about the types of requests it can process, and if it cannot process the request, it passes it to the next handler in the chain. This pattern effectively decouples the handlers, improving the system's scalability and maintainability.