Using the Chain of Responsibility Pattern in PHP
The Chain of Responsibility is a behavioral design pattern that allows you to create a chain of objects, where each object in the chain has the ability to either handle a request or pass it on to the next object in the chain. The pattern decouples the sender of a request from its receiver by allowing more than one object to handle the request and provides a way to handle the request in a flexible and extensible manner.
In this pattern, the objects are linked together to form a chain, and each object in the chain holds a reference to the next object in the chain. When a request is received, the first object in the chain will attempt to handle it. If it cannot handle the request, it will pass it on to the next object in the chain, and so on, until the request is either handled or there are no more objects in the chain.
This pattern allows you to add, remove or change the order of the objects in the chain without affecting the behavior of the system. It also simplifies the code by reducing the number of conditionals required to handle requests and increases the code reusability and maintainability of the system.
Article Highlights
- Forms a chain of handler functions where the request is passed through the chain and processed sequentially until it reaches the end of the chain.
- Benefit – Creates a set of reusable handlers that can be used across multiple projects or modules.
- Con – Some requests may hang if there are unexpected disruptions in the chain.
Chain of Responsibility Design Pattern PHP Code Example
<?php
interface Handler {
public function setNext($handler);
public function execute($request);
}
class Validator implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
function execute($request) {
//Implementation logic goes here
echo "Validating inputs\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class EmailSender implements Handler{
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Sending verification email\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Encryption implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Encrypting password\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Repository implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Save data in the database\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Logger implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "User signup successful!\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Terminator implements Handler {
private $next;
function setNext($handler) {
$this->next = null;
}
public function execute($request) {
//Implementation logic goes here
echo "Ending request response cycle!\n";
}
}
class ExceptionHandler implements Handler {
private $next;
public function setNext($handler) {
$this->next = null;
}
public function execute($request) {
//Implementation logic goes here
echo "Error in request. Terminating...\n";
}
}
class SignUpController {
public function __construct($request, ...$handlers) {
//The first chain function
$first = current($handlers);
$current = $first;
//Defines the chain
while(next($handlers)) {
$current->setNext(current($handlers));
$current = current($handlers);
}
$current->setNext(new Terminator()); //Inserts terminator at the end of the chain.
$first->execute($request); //Execute the request.
}
}
//Test Runner
function main() {
//Handlers
$validator = new Validator();
$emailSender = new EmailSender();
$encryption = new Encryption();
$repository = new Repository();
$logger = new Logger();
$request = []; //Empty mock request array.
$SignUpController = new SignUpController($request, $validator, $emailSender, $encryption, $repository, $logger);
}
/*
OUTPUT
Validating inputs
Sending verification email
Encrypting password
Save data in the database
User signup successful!
Ending request response cycle!
*/
?>
Table of Contents
- What is the Chain of Responsibility Pattern?
- Chain of Responsibility Pattern Example
- Problem 🙁
- Solution 🙂
- Benefits of the Chain of Responsibility Pattern
- Complete Architecture of Chain of Responsibility Pattern
- Pseudocode of Chain of Responsibility Pattern
- Pros and Cons of the Chain of Responsibility Pattern
- Use cases of Chain of Responsibility Pattern
- Conclusion

What is the Chain of Responsibility Pattern
“The Chain of Responsibility is a behavioral design pattern that allows you to create a chain of objects, where each object in the chain has the ability to either handle a request or pass it on to the next object in the chain. “

Chain of Responsibility Pattern Example
Consider a Signup service that performs a series of operations when a new user sends in the request with the appropriate data fields. The service does the following actions in series, consecutively, one after another.
A normal flow of operations would look as follows.
- Validates the user data.
- Sends a verification email to the user.
- Encrypts the credentials.
- Stores data in the database.
- Log a success message.
Failure in any of these operations will cut short the chain and call the exception handler function.

A basic no-frills solution that many of us would urge to implement immediately would be a monolithic application. Something similar to the example pseudocode.
<?php
function signUp($request) {
//Implementation logic goes here
echo "Validating inputs\n";
echo "Sending verification email\n";
echo "Encrypting password\n";
echo "Save data in the database\n";
echo "User signup successful!\n";
}
//Test runner function
function main() {
$request = []; //A mock request empty array object.
signUp($request);
}
/*
OUTPUT
Validating inputs
Sending verification email
Encrypting password
Save data in the database
User signup successful!
*/
?>
This solution works fine, except for some pain points from a design perspective.
Problem 🙁
Single Responsibility principle
“A class should have one and only one responsibility.”, states the single responsibility principle. The current solution has all the code in one single file as one module, which blatantly violates this principle. The resulting module is one large mess that is difficult to debug and maintain.

Ideally, a module should have one and only one responsibility. Such modules are highly cohesive and act independently in the application. Such modules are highly reusable and easy to debug because they are coherent in functionalities.
Open-closed principle
“A class should be closed for modification but open for extension.”, states the open/closed principle. Consider adding features to the applications. Adding more functions to such a large codebase with an undefined structure and design would be fairly difficult.
The functions may have dependencies, making it harder to extend this application without modifying the existing code. Modification, in turn, is also difficult because the module has no well-defined responsibilities.
Code duplication
We have mentioned reusability. Consider some other services say Login uses a subset of these functions. How would we reuse them? There is no other way except copying/pasting the existing code. Also, what if we want to add or remove functions dynamically?
Had they been independent modules, these questions won’t have bothered us. Luckily, we have some direction now.
Solution 🙂
Independent modules
We have repeatedly seen the system from a reusability perspective, and the current solution seems to fail miserably. Let’s try to refactor the code and define modules for each function.
<?php
class Validator {
function execute($request) {
//Implementation logic goes here
echo "Validating inputs\n";
}
}
class EmailSender {
public function execute($request) {
//Implementation logic goes here
echo "Sending verification email\n";
}
}
class Encryption {
public function execute($request) {
//Implementation logic goes here
echo "Encrypting password\n";
}
}
class Repository {
public function execute($request) {
//Implementation logic goes here
echo "Save data in the database\n";
}
}
class Logger {
public function execute($request) {
//Implementation logic goes here
echo "User signup successful!\n";
}
}
class ExceptionHandler {
public function execute($request) {
//Implementation logic goes here
echo "Error in request. Terminating...\n";
}
}
?>
Voila! We have independent modules which take one kind of responsibility. Interestingly, they all have the execute() method. Why is that necessary? We will figure that out in a moment.
Linking the modules
All the modules are in place so far, so good. But how would it pass the request to the successor handler? We have seen one way: call them in a sequence in an invoker function. That’s fine but what about the dynamic behavior? We want a way to add or remove handlers in the runtime.
So, we can define an attribute next in every class, referring to the next handler in the queue.
<?php
class Validator {
private $next;
function setNext($handler) {
$this->next = $handler;
}
function execute($request) {
//Implementation logic goes here
echo "Validating inputs\n";
//If the next handler is defined. The request is left hanging if the next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class EmailSender {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Sending verification email\n";
//If the next handler is defined. The request is left hanging if the next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Encryption {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Encrypting password\n";
//If the next handler is defined. The request is left hanging if the next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Repository {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Save data in the database\n";
//If the next handler is defined. The request is left hanging if the next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Logger {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "User signup successful!\n";
//If the next handler is defined. The request is left hanging if the next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class ExceptionHandler {
public function execute($request) {
//Implementation logic goes here
echo "Error in request. Terminating...\n";
}
}
?>
That’s how the handlers form a chain. The request goes through the chain until it reaches the very end of it – assuming a normal flow with no exceptions.
Chain of responsibility
Voila! We have almost implemented the “Chain of responsibility” principle. One final touch would be defining a Handler interface and letting the instances implement it so they are all bound to the same supertype.
<?php
interface Handler {
public function setNext($handler);
public function execute($request);
}
class Validator implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
function execute($request) {
//Implementation logic goes here
echo "Validating inputs\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class EmailSender implements Handler{
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Sending verification email\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Encryption implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Encrypting password\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Repository implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Save data in the database\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Logger implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "User signup successful!\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class ExceptionHandler implements Handler {
private $next;
public function setNext($handler) {
$this->next = null;
}
public function execute($request) {
//Implementation logic goes here
echo "Error in request. Terminating...\n";
}
}
?>
The terminator
Let’s also define a class that could end the request/response cycle. This handler usually comes at the end of the chain when the request is fulfilled. We do this so that the request doesn’t stay there hanging.
class Terminator implements Handler {
private $next;
function setNext($handler) {
$this->next = null;
}
public function execute($request) {
//Implementation logic goes here
echo "Ending request response cycle!\n";
}
}
Invoker Class
Let’s also define a class that sets up the chain and pass on the request to initiate the chain of responsibility.
class SignUpController {
public function __construct($request, ...$handlers) {
//The first chain function
$first = current($handlers);
$current = $first;
//Defines the chain
while(next($handlers)) {
$current->setNext(current($handlers));
$current = current($handlers);
}
$current->setNext(new Terminator()); //Inserts terminator at the end of the chain.
$first->execute($request); //Execute the request.
}
}
The SignUpController expects an indefinite number of handlers and sets the chain inside the constructor function. It also adds the terminator at the end of this chain.
We can define similar controllers for other services like Login.
Test drive
Time for a test drive. Let’s pass the handlers to the controller instance and see the output.
//Test Runner
function main() {
//Handlers
$validator = new Validator();
$emailSender = new EmailSender();
$encryption = new Encryption();
$repository = new Repository();
$logger = new Logger();
$request = []; //Empty mock request array.
$SignUpController = new SignUpController($request, $validator, $emailSender, $encryption, $repository, $logger);
}
/*
OUTPUT
Validating inputs
Sending verification email
Encrypting password
Save data in the database
User signup successful!
Ending request response cycle!
*/
Voila! Quite elegant. We have a robust design now because
- The handlers are independent modules.
- Controllers (invokers) are independent of the handlers.
- We can reuse the handlers in other controllers.
Handlers are also called middleware functions. Some really popular HTTP frameworks are based on this pattern. Google it 😉
Adding the exception handler
Finally, we can also add an exception handler in case something goes wrong so we can gracefully end the cycle. We already have the ExceptionHandler. Let’s use it in a handler just for demo purposes.
class Validator implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
function execute($request) {
try {
//Implementation logic goes here
echo "Validating inputs\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
catch(Exception $e) {
$exceptionHandler = new ExceptionHandler();
$exceptionHandler->execute($request);
}
}
}
Benefits of the Chain of Responsibility Pattern
- Decouples the sender of a request from its receiver. This means that the sender doesn’t need to know who the receiver is or what actions will be taken to handle the request.
- Provides flexibility and extensibility to the system. New handlers can be added or removed without affecting the existing handlers
- Simplifies the code by reducing the number of conditionals required to handle requests.
- You can create a set of reusable handlers that can be used across multiple projects or modules.
- Makes it easier to maintain the code by separating responsibilities and providing a clear structure. This makes it easier to debug, test, and modify the code.
Complete Architecture | Chain of Responsibility Pattern in PHP

Chain of Responsibility Pattern PHP Pseudocode Example
<?php
interface Handler {
public function setNext($handler);
public function execute($request);
}
class Validator implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
function execute($request) {
//Implementation logic goes here
echo "Validating inputs\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class EmailSender implements Handler{
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Sending verification email\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Encryption implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Encrypting password\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Repository implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "Save data in the database\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Logger implements Handler {
private $next;
function setNext($handler) {
$this->next = $handler;
}
public function execute($request) {
//Implementation logic goes here
echo "User signup successful!\n";
//If next handler is defined. The request is left hanging if next handler is not defined.
if($this->next) {
$this->next->execute($request);
}
}
}
class Terminator implements Handler {
private $next;
function setNext($handler) {
$this->next = null;
}
public function execute($request) {
//Implementation logic goes here
echo "Ending request response cycle!\n";
}
}
class ExceptionHandler implements Handler {
private $next;
public function setNext($handler) {
$this->next = null;
}
public function execute($request) {
//Implementation logic goes here
echo "Error in request. Terminating...\n";
}
}
class SignUpController {
public function __construct($request, ...$handlers) {
//The first chain function
$first = current($handlers);
$current = $first;
//Defines the chain
while(next($handlers)) {
$current->setNext(current($handlers));
$current = current($handlers);
}
$current->setNext(new Terminator()); //Inserts terminator at the end of the chain.
$first->execute($request); //Execute the request.
}
}
//Test Runner
function main() {
//Handlers
$validator = new Validator();
$emailSender = new EmailSender();
$encryption = new Encryption();
$repository = new Repository();
$logger = new Logger();
$request = []; //Empty mock request array.
$SignUpController = new SignUpController($request, $validator, $emailSender, $encryption, $repository, $logger);
}
/*
OUTPUT
Validating inputs
Sending verification email
Encrypting password
Save data in the database
User signup successful!
Ending request response cycle!
*/
?>
Pros and Cons of the Chain of Responsibility Pattern in PHP
Pros | Cons |
Satisfies the single responsibility principle by defining relevant handlers in separate modules. | Some requests may hang if there are unexpected disruptions in the chain. |
Satisfies the open-closed principle because we can add new handlers without affecting the existing code. | It can be hard to observe and debug during runtime (though we can attach a logger to every handler) |
The handler functions are reusable. | |
Allows adding or removing handlers from the chain dynamically. |
Where is the Chain of Responsibility Pattern Used
- Some popular HTTP frameworks use middleware functions that are based on this pattern.
- Windows systems handle mouse clicks or keyboard events using a chain of handlers.
- The Chain of Responsibility principle can create a chain of error handlers that each handle a specific type of error.
- When logging is used to record events in a system, the Chain of Responsibility principle can create a chain of loggers that each handle a specific level or type of log.
What is the Chain of Responsibility Pattern
The Chain of Responsibility is a behavioral design pattern that allows you to create a chain of objects, where each object in the chain can either handle a request or pass it on to the next object in the chain.
Using the Chain of Responsibility Pattern in PHP Today
Voila! We have covered a lot of ground. Let’s review what we have learned in this article. The Chain of Responsibility is a behavioral design pattern that allows you to create a chain of objects, where each object in the chain can either handle a request or pass it on to the next object in the chain.
The article features a signup service where a user can signup, and then the service calls a sequence of functions to process this request. The functions are written in one continuous block of code, which is hard to maintain, debug and test. Also, such a design affects the reusability of the components.
So, we separate the concerns by defining classes for all the different handlers and keep a reference to the successor handler so that we can dynamically create a chain of handlers. Using this approach, we can improve the reusability of these handler functions and make the system more dynamic and maintainable.
When a request is received, the first object in the chain will attempt to handle it. If it cannot handle the request, it will pass it on to the next object in the chain, and so on, until the request is either handled or there are no more objects in the chain.
This pattern allows you to add, remove or change the order of the objects in the chain without affecting the behavior of the system. It also simplifies the code by reducing the number of conditionals required to handle requests and increases the code reusability and maintainability of the system.
That’s all for now. Stay tuned for more design pattern articles at FuelingPHP.
Books on Design Patterns
Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.
Design Patterns: Elements of Reusable Object-Oriented Software

This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.
Learning PHP Design Patterns

This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.
Want to see our full review of books on design patterns? Read our huge review article on over 15 design pattern books.
Design Patterns in PHP Learning Series.
This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.
- What are Design Patterns in PHP?
- Books on Design Patterns
- Builder Design Pattern
- Strategy Design Pattern
- Factory Design Pattern
- Prototype Design Pattern
- Singleton Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Iterator Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Facade Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- State Design Pattern
- Observer Design Pattern
- Momento Design Pattern
- Mediator Design Pattner
- Chain of Responsibility Design Pattern