How to use the Chain of Responsibility design pattern in PHP for handling requests?

Member

by daisha , in category: PHP General , 2 years ago

How to use the Chain of Responsibility design pattern in PHP for handling requests?

Facebook Twitter LinkedIn Telegram Whatsapp

2 answers

by raven_corwin , 2 years ago

@daisha 

The Chain of Responsibility pattern is a behavioral design pattern that allows a group of objects to handle requests one by one in a chain-like structure. The pattern decouples the sender of a request from its receiver, by passing the request along a chain of potential receivers until one of them handles it.


Here's an example implementation of the Chain of Responsibility pattern in PHP for handling requests:


First, you need to define the handler interface that all handlers must implement:

1
2
3
4
interface Handler {
    public function setNext(Handler $handler): Handler;
    public function handle(Request $request): ?string;
}


Then, you can implement the base handler class, which provides the common behavior for all handlers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
abstract class AbstractHandler implements Handler {
    private ?Handler $nextHandler = null;

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

    public function handle(Request $request): ?string {
        if ($this->nextHandler) {
            return $this->nextHandler->handle($request);
        }
        return null;
    }
}


Next, you can define concrete handler classes that inherit from the base handler class and provide the specific behavior for handling different types of requests:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class ConcreteHandler1 extends AbstractHandler {
    public function handle(Request $request): ?string {
        if ($request->getType() === 'type1') {
            return 'Handled by ConcreteHandler1';
        }
        return parent::handle($request);
    }
}

class ConcreteHandler2 extends AbstractHandler {
    public function handle(Request $request): ?string {
        if ($request->getType() === 'type2') {
            return 'Handled by ConcreteHandler2';
        }
        return parent::handle($request);
    }
}


Finally, you can create the chain of handlers and pass the request to the first handler in the chain:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$handler1 = new ConcreteHandler1();
$handler2 = new ConcreteHandler2();
$handler1->setNext($handler2);

$request1 = new Request('type1');
$request2 = new Request('type2');
$request3 = new Request('type3');

$result1 = $handler1->handle($request1); // Handled by ConcreteHandler1
$result2 = $handler1->handle($request2); // Handled by ConcreteHandler2
$result3 = $handler1->handle($request3); // null


In this example, if a request of type 'type1' is received, it will be handled by ConcreteHandler1, and if a request of type 'type2' is received, it will be handled by ConcreteHandler2. If a request of any other type is received, it will not be handled and the handle method will return null.

by dalton_moen , 2 years ago

@daisha 

The Chain of Responsibility design pattern is a behavioral pattern that allows an object to pass a request along a chain of handlers until one of the handlers processes the request. This pattern is useful when there are multiple objects that can handle a request and it is not known in advance which object will handle the request.


Here is an example of how to implement the Chain of Responsibility pattern in PHP for handling requests:

  1. Define an abstract base class called Handler that declares a handleRequest method. This method takes a request parameter and returns either a response or null.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
abstract class Handler {
    protected $successor;

    public function setSuccessor(Handler $handler) {
        $this->successor = $handler;
    }

    public function handleRequest($request) {
        if ($this->successor) {
            return $this->successor->handleRequest($request);
        }

        return null;
    }
}


  1. Define concrete classes that extend the Handler class and implement their own handleRequest method. These classes represent the different handlers in the chain.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ConcreteHandler1 extends Handler {
    public function handleRequest($request) {
        if ($request == 'request1') {
            return 'Handled by ConcreteHandler1';
        } else {
            return parent::handleRequest($request);
        }
    }
}

class ConcreteHandler2 extends Handler {
    public function handleRequest($request) {
        if ($request == 'request2') {
            return 'Handled by ConcreteHandler2';
        } else {
            return parent::handleRequest($request);
        }
    }
}

class ConcreteHandler3 extends Handler {
    public function handleRequest($request) {
        if ($request == 'request3') {
            return 'Handled by ConcreteHandler3';
        } else {
            return parent::handleRequest($request);
        }
    }
}


  1. Create an instance of each concrete handler and set their successors in the order they should be executed.
1
2
3
4
5
6
$handler1 = new ConcreteHandler1();
$handler2 = new ConcreteHandler2();
$handler3 = new ConcreteHandler3();

$handler1->setSuccessor($handler2);
$handler2->setSuccessor($handler3);


  1. Pass a request to the first handler in the chain and let the chain handle the request.
1
2
$result = $handler1->handleRequest('request2');
echo $result; // Output: Handled by ConcreteHandler2


In this example, the request is passed to the first handler in the chain, which checks if it can handle the request. If it cannot, it passes the request to the next handler in the chain until a handler is found that can handle the request. If no handler can handle the request, null is returned.