PHPackages                             webpt/aquaduck - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. webpt/aquaduck

ActiveLibrary

webpt/aquaduck
==============

0.1(10y ago)063.5k↓30.4%2[2 PRs](https://github.com/webpt/aquaduck/pulls)3BSD-3-ClausePHPPHP &gt;=5.3.0

Since Jul 1Pushed 8y ago3 watchersCompare

[ Source](https://github.com/webpt/aquaduck)[ Packagist](https://packagist.org/packages/webpt/aquaduck)[ RSS](/packages/webpt-aquaduck/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (1)Versions (2)Used By (3)

Aquaduck
========

[](#aquaduck)

This package is heavily inspired by zendframework/zend-strategility [zendframework/zend-strategility](https://github.com/zendframework/zend-strategility).

Installation and Requirements
-----------------------------

[](#installation-and-requirements)

Install this library using composer:

```
$ composer require webpt/aquaduck
```

Usage
-----

[](#usage)

Creating a processing pipeline is trivially easy:

```
use Webpt\Aquaduck\Aquaduck;

require __DIR__ . '/../vendor/autoload.php';

$pipeline = new Aquaduck();

$pipeline->bind(function($value, $next) {
    $next($value + 5);
});

echo $pipeline(5); //10
```

Middleware
----------

[](#middleware)

What is middleware?

Middleware is code that exists which can take the incoming value (or object), perform actions based on it, and either return or pass delegation on to the next middleware in the queue.

Within Aquaduck, middleware can be:

- Any PHP callable that accepts, minimally, a single argument, and, optionally, a callable (for invoking the next middleware in the queue, if any).
- An object implementing `Webpt\Aquaduck\Middleware\MiddlewareInterface`. `Webpt\Aquaduck\Aquaduck` implements this interface.

Error Handlers
--------------

[](#error-handlers)

To handle errors, you can write middleware that accepts **exactly** 3 arguments:

```
function ($error, $subject, $next) { }
```

Alternately, you can implement `Webpt\Aquaduck\ErrorHandler\ErrorHandlerInterface`.

When using `Aquaduck`, as the queue is executed, if `$next()` is called with an argument, or if an exception is thrown, middleware will iterate through the queue until the first such error handler is found. That error handler can either complete the request, or itself call `$next()`. **Error handlers that call `$next()` SHOULD call it with the error it received itself, or with another error.**

Error handlers are usually attached at the end of middleware, to prevent attempts at executing non-error-handling middleware, and to ensure they can intercept errors from any other handlers.

Creating Middleware
-------------------

[](#creating-middleware)

To create middleware, write a callable capable of receiving minimally a single argument, and optionally a callback to call the next in the chain. If your middleware accepts a second argument, `$next`, if it is unable to complete the request, or allows further processing, it can call it to return handling to the parent middleware.

Middleware written in this way can be any of the following:

- Closures (as shown above)
- Functions
- Static class methods
- PHP array callbacks (e.g., `[ $class, 'run' ]`, where `$class` is a class instance)
- Invokable PHP objects (i.e., instances of classes implementing `__invoke()`)
- Objects implementing `Aquaduck\Middleware\MiddlewareInterface` (including `Webpt\Aquaduck\Aquaduck`)

Executing and composing middleware
----------------------------------

[](#executing-and-composing-middleware)

The easiest way to execute middleware is to write closures and attach them to a `Webpt\Aquaduck\Aquaduck` instance. You can nest `Aquaduck` instances to create groups of related middleware.

```
$pipe = new Aquaduck();       // Middleware collection
$pipe->bind(/* ... */);       // repeat as necessary

$superPipe = new Aquaduck();  // New Middleware collection
$superPipe->bind($pipe);      // Middleware attached as a group
```

API
---

[](#api)

The following make up the primary API of Aquaduck.

### Middleware

[](#middleware-1)

`Webpt\Aquaduck\Aquaduck` is the primary application interface, and has been discussed previously. Its API is:

```
class Aquaduck implements MiddlewareInterface
{
    public function bind($middleware, $priority = 1);
    public function __invoke(
        $subject,
        $out = null
    );
}
```

`bind()` takes up to two arguments. If only one argument is provided, `$middleware` will be assigned that value, and `$priority` will be assigned to the value `1`.

Middleware is executed in the order in which `$priority` is determined.

`__invoke()` is itself middleware. If `$out` is not provided, an instance of `Webpt\Aquaduck\FinalHandler` will be created, and used in the event that the pipe stack is exhausted. The callable should use the same signature as `Next()`:

```
function (
    $subject,
    $err = null
) {
}
```

Internally, `Aquaduck` creates an instance of `Webpt\Aquaduck\Next`, feeding it its queue, executes it, and returns a response.

### Next

[](#next)

`Webpt\Aquaduck\Next` is primarily an implementation detail of middleware, and exists to allow delegating to middleware registered later in the stack.

```
class Next
{
    public function __invoke(
        $subject,
        $err = null
    );
}
```

As examples:

#### Providing an altered subject:

[](#providing-an-altered-subject)

```
function ($subject, $next) use ($helperClass)
{
    $subject = $helperClass->help($subject);
    return $next($subject);
}
```

#### Raising an error condition

[](#raising-an-error-condition)

To raise an error condition, pass a non-null value as the second argument to `$next()`:

```
function ($subject, $next)
{
    try {
        // try some operation...
    } catch (Exception $e) {
        return $next($subject, $e); // Next registered error middleware will be invoked
    }
}
```

### FinalHandler

[](#finalhandler)

`Webpt\Aquaduck\FinalHandler` is a default implementation of middleware to execute when the stack exhausts itself. It expects two arguments when invoked: a subject, and an error condition (or `null` for no error).

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity30

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

3974d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/29004cd917fdd7e4a8cc4ddba16f0bbcd90829513c57fc96e3b4f3fcb53f7ead?d=identicon)[abacaphiliac](/maintainers/abacaphiliac)

![](https://www.gravatar.com/avatar/1104e04ccb26d61a408d46e2b18f39fa3cea9cc11a588e8d1ca2a7103c44c88b?d=identicon)[tklever](/maintainers/tklever)

---

Top Contributors

[![abacaphiliac](https://avatars.githubusercontent.com/u/1656273?v=4)](https://github.com/abacaphiliac "abacaphiliac (3 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/webpt-aquaduck/health.svg)

```
[![Health](https://phpackages.com/badges/webpt-aquaduck/health.svg)](https://phpackages.com/packages/webpt-aquaduck)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
