webpt / aquaduck
Installs: 56 954
Dependents: 3
Suggesters: 0
Security: 0
Stars: 0
Watchers: 4
Forks: 2
Open Issues: 2
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/phpunit: ^4.0
This package is not auto-updated.
Last update: 2024-11-23 18:16:19 UTC
README
This package is heavily inspired by zendframework/zend-strategility zendframework/zend-strategility.
Installation and Requirements
Install this library using composer:
$ composer require webpt/aquaduck
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
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
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
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
(includingWebpt\Aquaduck\Aquaduck
)
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
The following make up the primary API of Aquaduck.
Middleware
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
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:
function ($subject, $next) use ($helperClass) { $subject = $helperClass->help($subject); return $next($subject); }
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
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).