mike4git/chain-bundle
mike4git/chain-bundle is a lightweight PHP package for building chain-of-responsibility pipelines. It lets you compose handlers into reusable sequential workflows, pass requests through each step, and keep processing logic clean, modular, and easy to extend in framework-based applications.
chain-bundle is a small utility for composing handlers into a single, ordered chain (a lightweight chain-of-responsibility). Version 1.0.0 is the initial release, and the release notes are a single sentence — so budget 20 minutes to read the source before wiring it into anything important.
Minimal steps:
composer require <vendor>/chain-bundle
Then, in order:
src/ for the handler contract (typically handle()), the chain/runner class, and any ChainBundleServiceProvider. The contract's return type is the single most important detail — it determines whether a handler passes a value along, mutates it, or short-circuits.new-ing it, which is what makes handler constructor injection work.composer.json for the illuminate/* constraints — v1.0.0 packages often pin loosely and can drift on Laravel majors.First use case: a sequential processing pipeline where each step either enriches a payload or stops the chain — for example, validating and normalising an inbound webhook before dispatching jobs, or a multi-step order-import (parse → validate → dedupe → persist). Start with two or three handlers and a test, not a twelve-stage pipeline.
Register handlers as a list, not a discovery mechanism. The idiomatic shape is a service provider (often a domain-specific one, not AppServiceProvider) that pushes handlers onto the chain in explicit order:
$this->app->make(OrderChain::class)
->push(ParsePayload::class)
->push(ValidateOrder::class)
->push(DeduplicateOrder::class);
Explicit ordering in one place is far easier to reason about than annotation- or convention-based discovery.
Resolve handlers from the container. Handlers that are new-ed directly can't take dependencies. Keep handler constructors lean (a repository, a logger, maybe a config value) and let the container build them.
Treat the payload as immutable where you can. Returning a new DTO from each handler makes the chain trivially testable and prevents a downstream handler from silently mutating state an upstream one relied on. If the package's contract is by-reference, document that convention in the chain class's docblock.
Compare against Illuminate\Pipeline\Pipeline before committing. Laravel already ships a pipeline with via()/through()/then(). Reach for chain-bundle when you want a named, reusable, DI-resolved chain that multiple call sites invoke identically — not when you need a one-off pass over middleware. If your chain lives inside a single controller method, the framework pipeline is the lower-overhead choice.
Test the chain, and test each handler alone. A chain-level test asserts ordering and short-circuit behaviour; per-handler tests assert the transformation. A fake/stub chain is useful when a feature test only cares that the chain was invoked, not what it did.
Compose chains for larger flows. If the package supports nesting a chain as a handler, use it to build small named sub-flows (e.g. PaymentChain inside CheckoutChain) rather than one flat 15-step list.
null? false? a specific result object?) versus to continue. Write one test that pins this down and keep it forever.try/catch that logs with context. A broken chain is otherwise a stack trace with no indication of which step failed.config/chain-bundle.php is published, diff it against the package's own defaults on upgrade — early releases frequently rename keys within the first few minors.^1.0 is reasonable, but for a 1.0.0 with a one-line changelog, read the source at the exact tag you install and note the tag in your PR description. Expect the API to settle over the next few releases.AbstractHandler class that every handler inherits from.How can I help you explore Laravel packages today?