zendframework/zend-stratigility
Zend Stratigility is a lightweight middleware pipeline for PHP, built around PSR-7 HTTP messages. Compose request/response processing with reusable middleware, route-like piping, and error handling—ideal for building microservices or adding middleware to existing apps.
In this document, we outline the backwards breaking changes with version 3.0, and provide guidance on how to upgrade your application to be compatible.
We now support only PHP versions 7.1 and above. PHP 5.6 and 7.0 support has been dropped.
Stratigility now supports only PSR-15
interfaces. Support of http-interop/http-middleware has been dropped.
All middleware and request handlers must now implement PSR-15 interfaces, including those Stratigility implements.
As a result, a number of signatures have been changed. Primarily, these were a
matter of updating typehints on
Interop\Http\ServerMiddleware\DelegateInterface (defined in
http-interop/http-middleware
0.4 and up, an early draft of PSR-15) and
Interop\Http\Server\RequestHandlerInterface (defined in
http-interop/http-server-handler,
the immediate predecessor to the final spec) to
Psr\Http\Server\RequestHandlerInterface, and adding the return type hint
Psr\Http\Message\ResponseInterface.
Signatures affected include:
Zend\Stratigility\MiddlewarePipe::process()Zend\Stratigility\Middleware\ErrorHandler::process()Zend\Stratigility\Middleware\NotFoundHandler::process()Zend\Stratigility\Middleware\OriginalMessages::process()Zend\Stratigility\MiddlewarePipe::process()All of these classes now implement the PSR-15 MiddlewareInterface.
MiddlewarePipeWe now only allow piping Psr\Http\Server\MiddlewareInterface instances
into the MiddlewarePipe class.
In version 2, we had a number of internal utilities for identifying other types
of middleware (callable, double-pass, etc.), and would decorate those within the
pipe() method. This is no longer allowed.
If you wish to use those types, you will need to decorate them using the appropriate decorators as outlined in the Class additions section.
Additionally, MiddlewarePipe is now marked final, and may not be directly
extended. Decorate an instance if you wish to provide alternate behavior, or
create your own MiddlewareInterface implementation to provide alternate
internal logic.
Next::__construct(): the second parameter now typehints against the
PSR-15 RequestHandlerInterface.
Next::handle(): the method now provides a return typehint of
Psr\Http\Message\ResponseInterface.
MiddlewarePipe class is marked now as final and implements the new
interface MiddlewarePipeInterface.
MiddlewarePipe::pipe(): reduces the number of arguments to one, which now
typehints against Psr\Http\Server\MiddlewareInterface. This means the method
can no longer be used to segregate middleware by path. If you want to do that,
please use Zend\Stratigility\Middleware\PathMiddlewareDecorator to decorate
your middleware and to provide the path prefix it will run under. See the next
section for details.
MiddlewarePipe::process(): the second parameter now typehints against
Psr\Http\Server\RequestHandlerInterface, and provides a return typehint of
Psr\Http\Message\ResponseInterface.
ErrorHandler::__construct() and NotFoundHandler::__construct(): the first
parameter of each constructor now expects a PHP callable capable of
returning a PSR-7 ResponseInterface instance (instead of typehinting
directly against ResponseInterface). This paves the way for usage with the
upcoming PSR-17 (HTTP Message Factories) specification, and simplifies re-use
of a dependency injection container service (as otherwise you would need to
specify a discrete service per class that expects a response prototype, due to
mutability of the response body).
Zend\Stratigility\MiddlewarePipeInterface extends
Psr\Http\Server\MiddlewareInterface and Psr\Http\Server\RequestHandlerInterface,
and defines the method pipe(Psr\Http\Server\MiddlewareInterface $middleware) : void.
It is implemented by MiddlewarePipe.
Zend\Stratigility\Middleware\HostMiddlewareDecorator allows you to segregate
middleware by a static host name. This allows executing middleware only
if a particular host matches.
// Segregate to hosts matching 'example.com':
$pipeline->pipe(new HostMiddlewareDecorator('example.com', $middleware));
Alternately, use the host() utility function to generate the instance; see
below.
Zend\Stratigility\Middleware\PathMiddlewareDecorator allows you to segregate
middleware by a static URI path prefix. This allows executing middleware only
if a particular path matches, or segregating a sub-application by path.
// Segregate to paths matching '/foo' as the prefix:
$pipeline->pipe(new PathMiddlewareDecorator('/foo', $middleware));
Alternately, use the path() utility function to generate the instance; see
below.
Zend\Stratigility\Middleware\CallableMiddlewareDecorator provides the
functionality that was formerly provided by
Zend\Stratigility\Middleware\CallableInteropMiddlewareWrapper: it provides
the ability to decorate PHP callables that have the same or compatible
signatures to the PSR-15 MiddlewareInterface. This allows for one-off piping
of middleware:
$pipeline->pipe(new CallableMiddlewareDecorator(function ($req, $handler) {
// do some work
$response = $next($req, $handler);
// do some work
return $response;
});
The arguments and return value can be type-hinted, but do not need to be. The decorator provides some checking on the return value in order to raise an exception if a response is not returned.
Alternately, use the middleware() utility function to generate the instance;
see below.
Zend\Stratigility\Middleware\DoublePassMiddlewareDecorator provides the
functionality that was formerly provided by Zend\Stratigility\Middleware\CallableMiddlewareWrapper.
The class now makes the response prototype argument to the constructor
optional, and falls back to a zend-diactoros response instance if that library
is installed. Internally, it decorates the $handler as a callable.
$pipeline->pipe(new DoublePassMiddlewareDecorator(function ($req, $res, $next) {
// do some work
$response = $next($req, $res);
// do some work
return $response;
});
Per recommendations in previous versions, if you are using double-pass
middleware, do not operate on the response passed to the middleware; instead,
only operate on the response returned by $next, or produce a concrete
response yourself.
Alternately, use the doublePassMiddleware() utility function to create the
instance; see below.
Zend\Stratigility\Exception\ExceptionInterface - marker for
package-specific exceptions.
The following classes have been removed:
Zend\Stratigility\Delegate\CallableDelegateDecoratorZend\Stratigility\Middleware\CallableInteropMiddlewareWrapperZend\Stratigility\Middleware\CallableMiddlewareWrapperZend\Stratigility\Middleware\CallableMiddlewareWrapperFactoryZend\Stratigility\MiddlewareInterface (Please use the PSR-15
MiddlewareInterface instead.)Zend\Stratigility\NoopFinalHandlerZend\Stratigility\Route. This was an internal class used by MiddlewarePipe
and Next, and its removal should not affect consumers.The following exceptions have been removed:
Zend\Stratigility\Exception\InvalidMiddlewareException (this is no longer
thrown by MiddlewarePipe, and thus no longer necessary).Zend\Stratigility\Exception\InvalidRequestTypeExceptionMiddlewarePipe::__invoke(): the class is no longer invokable.
Use the method process instead.
MiddlewarePipe::setCallableMiddlewareDecorator(): since we now accept only
PSR-15 middleware implementations within MiddlewarePipe, this method is no
longer needed. Other middleware types should be decorated in a
MiddlewareInterface implementation prior to piping.
MiddlewarePipe::setResponsePrototype(): this method is no longer needed,
due to removing support for non-MiddlewareInterface types.
MiddlewarePipe::hasResponsePrototype(): this method is no longer needed,
due to removing support for non-MiddlewareInterface types.
MiddlewarePipe::raiseThrowables(): this method has been deprecated since
2.0.0, and slated for removal with this version.
Middleware\ErrorHandler::__invoke(): this class is no longer invokable.
Use the process method instead.
Middleware\NotFoundHandler::__invoke(): this class is no longer invokable.
Use the process method instead.
Next::__invoke(): this class is no longer invokable. Use the method handle
instead.
Next::next(): this method was a proxy to the handle() method, and no
longer of use, particularly as the class is an internal detail.
Next::process(): this method was a proxy to the handle() method, and no
longer of use, particularly as the class is an internal detail.
Next::raiseThrowables(): this method has been deprecated since 2.0.0, and
slated for removal with this version.
Release 3.0 adds the following utility functions:
function Zend\Stratigility\host(
string $host,
Psr\Http\Server\MiddlewareInterface $middleware
) : Zend\Stratigility\Middleware\HostMiddlewareDecorator
This is a convenience wrapper around instantiation of a
Zend\Stratigility\Middleware\HostMiddlewareDecorator instance:
$pipeline->pipe(host('example.com', $middleware));
function Zend\Stratigility\path(
string $pathPrefix,
Psr\Http\Server\MiddlewareInterface $middleware
) : Zend\Stratigility\Middleware\PathMiddlewareDecorator
This is a convenience wrapper around instantiation of a
Zend\Stratigility\Middleware\PathMiddlewareDecorator instance:
$pipeline->pipe(path('/foo', $middleware));
function Zend\Stratigility\middleware(
callable $middleware
) : Zend\Stratigility\Middleware\CallableMiddlewareDecorator
middleware() provides a convenient way to decorate callable middleware that
implements the PSR-15 middleware signature when piping it to your application.
$pipeline->pipe(middleware(function ($request, $handler) {
// ...
});
function Zend\Stratigility\doublePassMiddleware(
callable $middleware,
Psr\Http\Message\ResponseInterface $responsePrototype = null
) : Zend\Stratigility\Middleware\DoublePassMiddlewareDecorator
doublePassMiddleware() provides a convenient way to decorate middleware that
implements the double pass middleware signature when piping it to your application.
$pipeline->pipe(doublePassMiddleware(function ($request, $response, $next) {
// ...
});
If you are not using zend-diactoros as a PSR-7 implementation, you will need to pass a response prototype as well:
$pipeline->pipe(doublePassMiddleware(function ($request, $response, $next) {
// ...
}, $response);
How can I help you explore Laravel packages today?