blackmesa/chainofresponsibility-bundle
Installation Add the bundle via Composer:
composer require blackmesa/chainofresponsibility-bundle
Register the bundle in config/bundles.php:
return [
// ...
Blackmesa\ChainOfResponsibilityBundle\ChainOfResponsibilityBundle::class => ['all' => true],
];
Basic Configuration
Define a chain in config/packages/blackmesa_chain_of_responsibility.yaml:
blackmesa_chain_of_responsibility:
chains:
my_chain:
handlers:
- { class: 'App\Handler\FirstHandler' }
- { class: 'App\Handler\SecondHandler' }
First Use Case Inject the chain resolver and execute:
use Blackmesa\ChainOfResponsibilityBundle\Resolver\ChainResolverInterface;
class MyService
{
public function __construct(private ChainResolverInterface $chainResolver) {}
public function process()
{
$chain = $this->chainResolver->getChain('my_chain');
$result = $chain->execute(new MyRequest());
}
}
Handler Interface
Implement Blackmesa\ChainOfResponsibilityBundle\Handler\HandlerInterface:
class MyHandler implements HandlerInterface
{
public function handle(RequestInterface $request, HandlerInterface $nextHandler = null): ResponseInterface
{
// Process request
if ($nextHandler) {
return $nextHandler->handle($request);
}
return new Response();
}
}
Request/Response Objects
Use PSR-7 compatible objects (e.g., Nyholm\Psr7\Request, Nyholm\Psr7\Response) or custom DTOs.
Dynamic Chains Build chains programmatically:
$chain = $this->chainResolver->createChain([
new FirstHandler(),
new SecondHandler(),
]);
Middleware-Like Usage Replace Symfony middleware with chains for complex logic:
blackmesa_chain_of_responsibility:
chains:
auth_chain:
handlers:
- { class: 'App\Handler\AuthenticateHandler' }
- { class: 'App\Handler\AuthorizeHandler' }
Event Dispatching Use chains to process events:
$eventChain = $this->chainResolver->getChain('event_chain');
$eventChain->execute(new UserRegisteredEvent($user));
Dependency Injection Bind custom resolvers or handlers as services:
services:
App\Handler\CustomHandler:
tags: ['blackmesa_chain.handler']
Circular Dependencies
Avoid recursive handler calls (e.g., HandlerA calling HandlerB which calls HandlerA again).
Configuration Overrides
Bundle config is merged; ensure no accidental overrides in config/packages/.
Handler Order Matters Chains execute handlers in declaration order. Reorder via YAML or programmatically.
Logging Enable debug mode to log chain execution:
blackmesa_chain_of_responsibility:
debug: true
Breakpoints
Use var_dump($request) or IDE breakpoints in handle() methods.
Validation Check for missing handlers in config:
php bin/console debug:container blackmesa_chain_of_responsibility
Custom Resolvers
Implement ChainResolverInterface for dynamic chains:
class DynamicChainResolver implements ChainResolverInterface
{
public function getChain(string $name): ChainInterface
{
// Logic to build chains at runtime
}
}
Handler Decorators Wrap handlers for cross-cutting concerns:
class LoggingHandlerDecorator implements HandlerInterface
{
public function __construct(private HandlerInterface $handler) {}
public function handle(RequestInterface $request, HandlerInterface $next = null)
{
\Log::info('Handling request', ['request' => $request]);
return $this->handler->handle($request, $next);
}
}
Configuration Dumping Dump chain structure for debugging:
$chain = $this->chainResolver->getChain('my_chain');
\Log::debug('Chain structure:', $chain->getHandlers());
How can I help you explore Laravel packages today?