What It Is
The Chain of Responsibility pattern passes a request along a chain of handlers. Each handler either deals with the request or hands it to the next one. The sender only knows the first link — never who will actually solve it.
Example: A Support Line
A problem enters at the chat bot. What the bot cannot fix goes to tech support; what tech support cannot fix goes to the manager, who handles everything that arrives.
Pass it on until someone can
"No internet" travels one step and stops at tech support; the refund request travels the whole chain to the manager. The caller wrote the same one line both times. The nullsafe call $this->next?->handle() simply stops at the end of the chain.
Output: PHP script
<?php
class Handler {
public function __construct(
private string $name,
private \Closure $canFix,
private ?Handler $next = null,
) {}
public function handle(string $problem): void {
if (($this->canFix)($problem)) {
echo $this->name, " solved: ", $problem, "\n";
return;
}
echo $this->name, " passes it on\n";
$this->next?->handle($problem);
}
}
$manager = new Handler("manager", fn(string $p) => true);
$tech = new Handler("tech support", fn(string $p) => $p === "no internet", $manager);
$bot = new Handler("chat bot", fn(string $p) => $p === "forgot password", $tech);
$bot->handle("no internet");
echo "---\n";
$bot->handle("refund request");
When to Use It
Use it when several parties might handle a request and the right one is not known in advance — support escalation, middleware, event handling, approval workflows.
Skip it when the handler is always known — call it directly. A chain with one link, or one that always ends at the same link, is a plain function call in costume.
Pros and Cons
Pros: sender and receivers are decoupled; links can be added, removed and reordered freely; each handler stays small.
Cons: no guarantee anyone handles the request — a broken chain swallows it silently; following a request through many links makes debugging slower.