Caution
The documentation you are viewing is for an older version of this component.
Switch to the latest (v3) version.
Features
Applications
In zend-expressive, you define a Zend\Expressive\Application
instance and
execute it. The Application
instance is itself
middleware
that composes:
- a router, for dynamically routing requests to middleware.
- a dependency injection container, for retrieving middleware to dispatch.
- a default delegate (Expressive 2.X) or final handler
- an emitter, for emitting the response when application execution is complete.
You can define the Application
instance in several ways:
- Direct instantiation, which requires providing several dependencies.
- The
AppFactory
, which will use some common defaults, but allows injecting alternate container and/or router implementations. - Via a dependency injection container; we provide a factory for setting up all aspects of the instance via configuration and other defined services.
Regardless of how you setup the instance, there are several methods you will likely interact with at some point or another.
Instantiation
As noted at the start of this document, we provide several ways to create an
Application
instance.
Constructor
If you wish to manually instantiate the Application
instance, it has the
following constructor:
/**
* @param Zend\Expressive\Router\RouterInterface $router
* @param null|Psr\Container\ContainerInterface $container IoC container from which to pull services, if any.
* @param null|Interop\Http\ServerMiddleware\DelegateInterface $defaultDelegate
* Delegate to invoke when the internal middleware pipeline is exhausted
* without returning a response.
* @param null|Zend\Diactoros\Response\EmitterInterface $emitter Emitter to use when `run()` is
* invoked.
*/
public function __construct(
Zend\Expressive\Router\RouterInterface $router,
Psr\Container\ContainerInterface $container = null,
Interop\Http\ServerMiddleware\DelegateInterface $defaultDelegate = null,
Zend\Diactoros\Response\EmitterInterface $emitter = null
);
If no container is provided at instantiation, then all routed and piped middleware must be provided as callables.
AppFactory
- Deprecated since version 2.2; instantiate
Application
directly and/or use aZend\Stratigility\MiddlewarePipe
instance instead.
Zend\Expressive\AppFactory
provides a convenience layer for creating an
Application
instance; it makes the assumption that you will use defaults in
most situations, and likely only change which container and/or router you wish
to use. It has the following signature:
AppFactory::create(
Psr\Container\ContainerInterface $container = null,
Zend\Expressive\Router\RouterInterface $router = null
);
When no container or router are provided, it defaults to:
- zend-servicemanager for the container.
- FastRoute for the router.
Container factory
We also provide a factory that can be consumed by a PSR-11 dependency injection container; see the container factories documentation for details.
Adding routable middleware
We discuss routing vs piping elsewhere; routing is the act of dynamically matching an incoming request against criteria, and it is one of the primary features of zend-expressive.
Regardless of which router implementation you use, you can use the following methods to provide routable middleware:
route()
route()
has the following signature:
public function route(
$pathOrRoute,
$middleware = null,
array $methods = null,
$name = null
) : Zend\Expressive\Router\Route
where:
$pathOrRoute
may be either a string path to match, or aZend\Expressive\Router\Route
instance.$middleware
must be present if$pathOrRoute
is a string path, and must be:- a callable;
- a service name that resolves to valid middleware in the container;
- a fully qualified class name of a constructor-less class;
- an array of any of the above; these will be composed in order into a
Zend\Stratigility\MiddlewarePipe
instance.
$methods
must be an array of HTTP methods valid for the given path and middleware. If null, it assumes any method is valid.$name
is the optional name for the route, and is used when generating a URI from known routes. See the section on route naming for details.
This method is typically only used if you want a single middleware to handle multiple HTTP request methods.
get(), post(), put(), patch(), delete(), any()
Each of the methods get()
, post()
, put()
, patch()
, delete()
, and any()
proxies to route()
and has the signature:
function (
$pathOrRoute,
$middleware = null,
$name = null
) : Zend\Expressive\Router\Route
Essentially, each calls route()
and specifies an array consisting solely of
the corresponding HTTP method for the $methods
argument.
Piping
Because zend-expressive builds on zend-stratigility,
and, more specifically, its MiddlewarePipe
definition, you can also pipe
(queue) middleware to the application. This is useful for adding middleware that
should execute on each request, defining error handlers, and/or segregating
applications by subpath.
The signature of pipe()
is:
public function pipe($pathOrMiddleware, $middleware = null)
where:
$pathOrMiddleware
is either a string URI path (for path segregation), a callable middleware, or the service name for a middleware to fetch from the composed container.$middleware
is required if$pathOrMiddleware
is a string URI path. It can be one of:- a callable;
- a service name that resolves to valid middleware in the container;
- a fully qualified class name of a constructor-less class;
- an array of any of the above; these will be composed in order into a
Zend\Stratigility\MiddlewarePipe
instance.
Unlike Zend\Stratigility\MiddlewarePipe
, Application::pipe()
allows
fetching middleware by service name. This facility allows lazy-loading of
middleware only when it is invoked. Internally, it wraps the call to fetch and
dispatch the middleware inside a closure.
Additionally, we define a new method, pipeErrorHandler()
, with the following
signature:
public function pipeErrorHandler($pathOrMiddleware, $middleware = null)
It acts just like pipe()
except when the middleware specified is a service
name; in that particular case, when it wraps the middleware in a closure, it
uses the error handler signature:
function ($error, ServerRequestInterface $request, ResponseInterface $response, callable $next);
Read the section on piping vs routing for more information.
Registering routing and dispatch middleware
Routing is accomplished via dedicated middleware, Zend\Expressive\Middleware\RouteMiddleware
;
similarly, dispatching of routed middleware has a corresponding middleware,
Zend\Expressive\Middleware\DispatchMiddleware
. Each can be piped/registered
with other middleware platforms if desired.
These methods MUST be piped to the application so that the application will route and dispatch routed middleware. This is done using the following methods:
$app->pipeRoutingMiddleware();
$app->pipeDispatchMiddleware();
See the section on piping to see how you can register non-routed middleware and create layered middleware applications.
Changed in version 2.2
Starting in version 2.2, the methods
pipeRoutingMiddleware
andpipeDispatchMiddleware
are deprecated in favor of piping the middleware manually.Additionally, the middleware has been ported to the zend-expressive-router package, under the namespace
Zend\Expressive\Router\Middleware
. We suggest piping them by service name. Please see our migration documentation for more details, and for information on how to automatically update your application.
Retrieving dependencies
As noted in the intro, the Application
class has several dependencies. Some of
these may allow further configuration, or may be useful on their own, and have
methods for retrieving them. They include:
getContainer()
: returns the composed PSR-11 container instance (used to retrieve routed middleware).getEmitter()
: returns the composed emitter, typically aZend\Expressive\Emitter\EmitterStack
instance.getDefaultDelegate()
: retrieves the default delegate to use when the internal middleware pipeline is exhausted without returning a response. If none is provided at instantiation, this method will do one of the following:- If no container is composed, instanatiates a
Zend\Expressive\Delegate\NotFoundDelegate
using the composed response prototype only. - If a container is composed, but does not have the
Zend\Expressive\Delegate\DefaultDelegate
service, it creates and invokes an instance ofZend\Expressive\Container\NotFoundDelegateFactory
, passing it the composed container, and uses the value created. - If a container is composed and contains the
Zend\Expressive\Delegate\DefaultDelegate
service, it returns that.
- If no container is composed, instanatiates a
Deprecated
Each of the above methods are deprecated starting in version 2.2, and will be removed in version 3.0.
Executing the application: run()
When the application is completely setup, you can execute it with the run()
method. The method may be called with no arguments, but has the following
signature:
public function run(
ServerRequestInterface $request = null,
ResponseInterface $response = null
);
Found a mistake or want to contribute to the documentation? Edit this page on GitHub!