Back to skills
extension
Category: Development & EngineeringNo API key required

acc-create-chain-of-responsibility

Generates Chain of Responsibility pattern for PHP 8.5. Creates handler chains for request processing with middleware-style composition. Includes unit tests.

personAuthor: jakexiaohubgithub

Chain of Responsibility Pattern Generator

Creates Chain of Responsibility pattern infrastructure for sequential request processing.

When to Use

| Scenario | Example | |----------|---------| | Multiple processors | Validation, discounts, approvals | | Unknown handlers | Plugin systems | | Priority processing | First match wins | | Middleware | HTTP pipeline, logging |

Component Characteristics

HandlerInterface

  • Defines handle method
  • Optional setNext for linking
  • Returns result or delegates

AbstractHandler

  • Implements chain linking
  • Provides base handle logic
  • Simplifies concrete handlers

Concrete Handlers

  • Process specific requests
  • Decide to handle or pass
  • Can terminate or continue chain

Generation Process

Step 1: Generate Handler Interface

Path: src/Domain/{BoundedContext}/Handler/

  1. {Name}HandlerInterface.php — Handler contract with setNext and handle methods

Step 2: Generate Abstract Handler

Path: src/Domain/{BoundedContext}/Handler/

  1. Abstract{Name}Handler.php — Base class with chain linking logic

Step 3: Generate Concrete Handlers

Path: src/Domain/{BoundedContext}/Handler/

  1. {Specific}{Name}Handler.php — Specific handler implementations

Step 4: Generate Chain Builder (Optional)

Path: src/Domain/{BoundedContext}/Handler/

  1. {Name}ChainBuilder.php — Fluent builder for chain construction

Step 5: Generate Tests

  1. {Handler}Test.php — Individual handler tests
  2. {Name}ChainTest.php — Chain integration tests

File Placement

| Component | Path | |-----------|------| | Handler Interface | src/Domain/{BoundedContext}/Handler/ | | Abstract Handler | src/Domain/{BoundedContext}/Handler/ | | Concrete Handlers | src/Domain/{BoundedContext}/Handler/ | | Chain Builder | src/Domain/{BoundedContext}/Handler/ | | Pipeline | src/Application/Pipeline/ | | Unit Tests | tests/Unit/Domain/{BoundedContext}/Handler/ |


Naming Conventions

| Component | Pattern | Example | |-----------|---------|---------| | Interface | {Name}HandlerInterface | ValidationHandlerInterface | | Abstract | Abstract{Name}Handler | AbstractValidationHandler | | Concrete | {Specific}{Name}Handler | EmailValidationHandler | | Builder | {Name}ChainBuilder | ValidationChainBuilder | | Test | {ClassName}Test | EmailValidationHandlerTest |


Quick Template Reference

Handler Interface

interface {Name}HandlerInterface
{
    public function setNext(self $handler): self;
    public function handle({RequestType} $request): {ResultType};
}

Abstract Handler

abstract class Abstract{Name}Handler implements {Name}HandlerInterface
{
    private ?{Name}HandlerInterface $next = null;

    public function setNext({Name}HandlerInterface $handler): {Name}HandlerInterface
    {
        $this->next = $handler;
        return $handler;
    }

    public function handle({RequestType} $request): {ResultType}
    {
        if ($this->next !== null) {
            return $this->next->handle($request);
        }
        return $this->getDefaultResult();
    }

    abstract protected function getDefaultResult(): {ResultType};
}

Concrete Handler

final class {Specific}Handler extends Abstract{Name}Handler
{
    public function handle({RequestType} $request): {ResultType}
    {
        if ($this->canHandle($request)) {
            return $this->process($request);
        }
        return parent::handle($request);
    }

    private function canHandle({RequestType} $request): bool
    {
        return {condition};
    }
}

Chain Builder

final class {Name}ChainBuilder
{
    private array $handlers = [];

    public function add({Name}HandlerInterface $handler): self
    {
        $this->handlers[] = $handler;
        return $this;
    }

    public function build(): {Name}HandlerInterface
    {
        $first = $this->handlers[0];
        $current = $first;
        for ($i = 1; $i < count($this->handlers); $i++) {
            $current = $current->setNext($this->handlers[$i]);
        }
        return $first;
    }
}

Usage Examples

Validation Chain

$chain = (new ValidationChainBuilder())
    ->add(new NotEmptyValidationHandler('email'))
    ->add(new EmailValidationHandler('email'))
    ->add(new MinLengthValidationHandler('password', 8))
    ->build();

$result = $chain->validate($request);

if ($result->hasErrors()) {
    throw new ValidationException($result->getMessage());
}

Discount Chain

$vipHandler = new VipDiscountHandler();
$promoHandler = new PromoCodeDiscountHandler($promoCodes);
$bulkHandler = new BulkDiscountHandler();

$vipHandler->setNext($promoHandler);
$promoHandler->setNext($bulkHandler);

$result = $vipHandler->apply($discountRequest);

Anti-patterns to Avoid

| Anti-pattern | Problem | Solution | |--------------|---------|----------| | Circular Chain | Infinite loop | Validate chain structure | | No Default | Unhandled requests | Provide fallback handler | | Coupled Handlers | Hard to reorder | Use interface properly | | Missing Builder | Manual chain assembly | Create ChainBuilder | | State in Handler | Non-reentrant | Make handlers stateless |


References

For complete PHP templates and examples, see:

  • references/templates.md — Handler Interface, Abstract Handler, Concrete Handler, Chain Builder, Pipeline templates
  • references/examples.md — Validation Chain, Discount Chain examples and tests