Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pipeline Laravel Package

descom/pipeline

A Laravel package implementing the pipeline pattern, letting you pass data through a sequence of reusable stages for cleaner, composable business logic. Define pipes with a simple API and keep request processing modular and testable.

View on GitHub
Deep Wiki
Context7

Getting Started

Before writing any feature code, treat this package as a source-audit exercise: 0 stars, 0 dependents, and a single 2025-04-09 release mean the README is likely your only documentation and the tests/ directory is your real spec.

  1. Install and inspect.

    composer require descom/pipeline
    composer show descom/pipeline          # confirm version + autoloaded provider
    

    Laravel will auto-discover the service provider via extra.laravel.providers in its composer.json. If it does not, register it manually in bootstrap/providers.php.

  2. Read in this order: README.md → src/ (find the plugin/stage contract and the pipeline entry point) → tests/ (copy a working example verbatim before improvising). The contract interface is the single most important file — it defines the handle()-style signature every plugin must satisfy.

  3. Publish config if offered.

    php artisan vendor:publish --provider="Descom\Pipeline\PipelineServiceProvider"
    

    Verify the provider FQCN from composer.json first; there is no guarantee a config file ships.

  4. First use case: a checkout flow where each "plugin" is one isolated stage — ValidateStock → ApplyDiscount → ChargePayment → SendReceipt. Instead of one 200-line service method, each stage is a class you can test, reorder, or swap per tenant. The package's value is the injection layer: stages are resolved from a registry/config rather than hardcoded in an array.

Skeleton (confirm exact method names against src/ — the shape below is the standard Laravel pipeline contract this package almost certainly wraps):

$result = app(Pipeline::class)
    ->send(new CheckoutPayload($order))
    ->through(config('pipeline.checkout'))   // injected plugin classes
    ->thenReturn();

Implementation Patterns

One class per plugin, single responsibility. Each plugin implements the package's contract with a handle($payload, Closure $next) signature. Keep plugins small and pure where possible; return the payload or a new one, never null.

Register via config, not hardcoded arrays. The whole point of "inject plugins" is that the stage list is data. Put ordered arrays in config/pipeline.php keyed by flow name (checkout, onboarding, webhooks) and resolve them at call sites. This lets you reorder stages without touching application code and lets ops toggle a stage via env/feature flag.

Per-tenant / per-plan injection. Bind a resolver that returns a different stage list based on the authenticated tenant:

$this->app->bind('pipeline.checkout', fn () => match (tenant()->plan) {
    'enterprise' => [ValidateStock::class, ApplyDiscount::class, ChargePayment::class, FraudCheck::class],
    default      => [ValidateStock::class, ChargePayment::class],
});

Async wrapping. When stages do I/O (payment gateways, webhooks), wrap the pipeline call in a queued job and pass a DTO, not an Eloquent model — serialization of models across queue boundaries is a classic source of stale-state bugs.

Testing pattern. The fastest way to gain confidence in an unproven package is to test your stages in isolation and test one integration path end-to-end:

$mock = Mockery::mock(ChargePayment::class);
$mock->shouldReceive('handle')->once()->andReturnUsing(fn ($p, $n) => $n($p));
$this->app->instance(ChargePayment::class, $mock);

If the package resolves plugins from the container (most do), $this->app->instance() swaps them cleanly. If it instantiates with new, you'll need to refactor registration to go through the container — a red flag worth noting.

Integration tip: expose the pipeline behind your own thin CheckoutService wrapper. That gives you one seam to swap the package out later without touching controllers.

Gotchas and Tips

  • Zero-adoption risk is the #1 gotcha. With 0 stars and 0 dependents, there is no community backstop for bugs. Fork it, or wrap it behind an interface you control, before it touches revenue paths. Budget for reading every line of src/.
  • Pipeline order is load-bearing. A stage that returns a new payload type will break the next stage's type hints silently (PHP only fails at runtime). Standardize on one payload DTO, or document the transformation contract per stage.
  • Halting vs. continuing. Laravel-style pipelines stop on a thrown exception; they do not skip a stage automatically. If you need "skip on condition," the plugin must call $next($payload) early — don't assume the package adds conditional logic it doesn't document.
  • thenReturn() vs then(). thenReturn() discards the final return value; then(fn ($p) => ...) lets you post-process. Pick deliberately, and be consistent across call sites.
  • Method-name drift. Since there's no docs guarantee, the actual methods may be plugins(), through(), or a custom name. Grep src/ for function before writing code — don't cargo-cult Laravel's Illuminate\Pipeline API.
  • Config caching bites. If stage lists live in config, php artisan config:clear after edits in dev. In production, config:cache is fine — but ensure your per-tenant resolver doesn't read env() directly at runtime.
  • Debugging: the cleanest debugger is a temporary Log::info(class_basename($this), ['payload' => $payload]) at the top of each handle(). For a package with no docs, this is faster than reasoning about the container.
  • Extension points to verify in src/: (a) the plugin contract binding — can you rebind it? (b) the registry/config source — can you add a custom resolver? (c) exception handling — can you intercept failures? If any of these are hardcoded final classes, the package will fight you the moment requirements change.
  • Version pinning. With one release, pin exact ("descom/pipeline": "1.0.0" or whatever the tag is) and commit composer.lock. A surprise patch could change the contract with no changelog to warn you.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle