Name: zend-expressive-helpers
Owner: Zend Framework
Description: Helper classes for Expressive
Created: 2015-12-04 16:16:30.0
Updated: 2018-01-14 19:57:25.0
Pushed: 2017-12-14 15:19:50.0
Homepage: null
Size: 298
Language: PHP
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Helper classes for Expressive.
Install this library using composer:
mposer require zendframework/zend-expressive-helpers
We recommend using a dependency injection container, and typehint against container-interop. We can recommend the following implementations:
composer require zendframework/zend-servicemanager
composer require mouf/pimple-interop
composer require aura/di
Zend\Expressive\Helper\UrlHelper
provides the ability to generate a URI path
based on a given route defined in the Zend\Expressive\Router\RouterInterface
.
The provided Zend\Expressive\Helper\UrlHelperMiddleware
can look for a
Zend\Expressive\Router\RouteResult
request attribute, and, if present, inject
the UrlHelper
with it; when this occurs, if the route being used to generate
a URI was also the one matched during routing, you can provide a subset of
routing parameters, and any not provided will be pulled from those matched.
In order to use the helper, you will need to instantiate it with the current
RouterInterface
. The factory Zend\Expressive\Helper\UrlHelperFactory
has
been provided for this purpose, and can be used trivially with most
dependency injection containers implementing container-interop:
Zend\Expressive\Helper\UrlHelper;
Zend\Expressive\Helper\UrlHelperFactory;
end-servicemanager:
vices->setFactory(UrlHelper::class, UrlHelperFactory::class);
imple:
ple[UrlHelper::class] = $pimple->share(function ($container) {
$factory = new UrlHelperFactory();
return $factory($container);
ura.Di:
tainer->set(UrlHelperFactory::class, $container->lazyNew(UrlHelperFactory::class));
tainer->set(
UrlHelper::class,
$container->lazyGetCall(UrlHelperFactory::class, '__invoke', $container)
The following dependency configuration will work for all three when using the Expressive skeleton:
rn ['dependencies' => [
'factories' => [
UrlHelper::class => UrlHelperFactory::class,
],
Factory requires RouterInterface The factory requires that a service named
Zend\Expressive\Router\RouterInterface
is present, and will raise an exception if the service is not found.
For the helper to be useful, it must be injected with a
Zend\Expressive\Router\RouteResult
. To automate this, we provide a middleware
class, UrlHelperMiddleware
, which accepts the UrlHelper
instance.
When invoked, it looks for a RouteResult
request attribute, and, if found,
injects it into the UrlHelper
. To register this middleware, you will need to:
UrlHelperMiddleware
as a service in your container.UrlHelperMiddleware
as middleware between the Expressive
routing and dispatch middleware.The following examples demonstrate registering the services.
Zend\Expressive\Helper\UrlHelperMiddleware;
Zend\Expressive\Helper\UrlHelperMiddlewareFactory;
end-servicemanager:
vices->setFactory(UrlHelperMiddleware::class, UrlHelperMiddlewareFactory::class);
imple:
ple[UrlHelperMiddleware::class] = $pimple->share(function ($container) {
$factory = new UrlHelperMiddlewareFactory();
return $factory($container);
ura.Di:
tainer->set(UrlHelperMiddlewareFactory::class, $container->lazyNew(UrlHelperMiddlewareFactory::class));
tainer->set(
UrlHelperMiddleware::class,
$container->lazyGetCall(UrlHelperMiddlewareFactory::class, '__invoke', $container)
To register the UrlHelperMiddleware
:
Zend\Expressive\Helper\UrlHelperMiddleware;
->pipeRoutingMiddleware();
->pipe(UrlHelperMiddleware::class);
->pipeDispatchMiddleware();
r use configuration:
'middleware_pipeline' => [
'routing' => [
'middleware' => [
Zend\Expressive\Container\ApplicationFactory::ROUTING_MIDDLEWARE,
UrlHelperMiddleware::class,
Zend\Expressive\Container\ApplicationFactory::DISPATCH_MIDDLEWARE,
],
'priority' => 1,
],
],
The following dependency configuration will work for all three when using the Expressive skeleton:
rn [
'dependencies' => [
'invokables' => [
],
'factories' => [
UrlHelper::class => UrlHelperFactory::class,
UrlHelperMiddleware::class => UrlHelperMiddlewareFactory::class,
],
],
'middleware_pipeline' => [
'routing' => [
'middleware' => [
Zend\Expressive\Container\ApplicationFactory::ROUTING_MIDDLEWARE,
UrlHelperMiddleware::class,
Zend\Expressive\Container\ApplicationFactory::DISPATCH_MIDDLEWARE,
],
'priority' => 1,
],
],
Compose the helper in your middleware (or elsewhere), and then use it to generate URI paths:
Zend\Expressive\Helper\UrlHelper;
s FooMiddleware
private $helper;
public function __construct(UrlHelper $helper)
{
$this->helper = $helper;
}
public function __invoke($request, $response, callable $next)
{
$response = $response->withHeader(
'Link',
$this->helper->generate('resource', ['id' => 'sha1'])
);
return $next($request, $response);
}
You can use the methods generate()
and __invoke()
interchangeably (i.e., you
can use the helper as a function if desired). The signature is:
tion ($routeName, array $params = []) : string
Where:
$routeName
is the name of a route defined in the composed router. You may
omit this argument if you want to generate the path for the currently matched
request.$params
is an array of substitutions to use for the provided route, with the
following behavior:RouteResult
is composed in the helper, and the $routeName
matches
it, the provided $params
will be merged with any matched parameters, with
those provided taking precedence.RouteResult
is not composed, or if the composed result does not match
the provided $routeName
, then only the $params
provided will be used
for substitutions.$params
are provided, and the $routeName
matches the currently
matched route, then any matched parameters found will be used.
parameters found will be used.$params
are provided, and the $routeName
does not match the
currently matched route, or if no route result is present, then no
substitutions will be made.Each method will raise an exception if:
$routeName
is provided, and no RouteResult
is composed.$routeName
is provided, a RouteResult
is composed, but that result
represents a matching failure.$routeName
is not defined in the router.If your application is running under a subdirectory, or if you are running
pipeline middleware that is intercepting on a subpath, the paths generated
by the router may not reflect the base path, and thus be invalid. To
accommodate this, the UrlHelper
supports injection of the base path; when
present, it will be prepended to the path generated by the router.
As an example, perhaps you have middleware running to intercept a language
prefix in the URL; this middleware could then inject the UrlHelper
with the
detected language, before stripping it off the request URI instance to pass on
to the router:
Locale;
Zend\Expressive\Helper\UrlHelper;
s LocaleMiddleware
private $helper;
public function __construct(UrlHelper $helper)
{
$this->helper = $helper;
}
public function __invoke($request, $response, $next)
{
$uri = $request->getUri();
$path = $uri->getPath();
if (! preg_match('#^/(?P<lang>[a-z]{2})/#', $path, $matches)) {
return $next($request, $response);
}
$lang = $matches['lang'];
Locale::setDefault($lang);
$this->helper->setBasePath($lang);
return $next(
$request->withUri(
$uri->withPath(substr($path, 3))
),
$response
);
}
(Note: if the base path injected is not prefixed with /
, the helper will add
the slash.)
Paths generated by the UriHelper
from this point forward will have the
detected language prefix.
Zend\Expressive\Helper\ServerUrlHelper
provides the ability to generate a full
URI by passing only the path to the helper; it will then use that path with the
current Psr\Http\Message\UriInterface
instance provided to it in order to
generate a fully qualified URI.
In order to use the helper, you will need to inject it with the current
UriInterface
from the request instance. To automate this, we provide
Zend\Expressive\Helper\ServerUrlMiddleware
, which composes a ServerUrl
instance, and, when invoked, injects it with the URI instance.
As such, you will need to:
ServerUrlHelper
as a service in your container.ServerUrlMiddleware
as a service in your container.ServerUrlMiddleware
early in your middleware pipeline.The following examples demonstrate registering the services.
Zend\Expressive\Helper\ServerUrlHelper;
Zend\Expressive\Helper\ServerUrlMiddleware;
Zend\Expressive\Helper\ServerUrlMiddlewareFactory;
end-servicemanager:
vices->setInvokableClass(ServerUrlHelper::class, ServerUrlHelper::class);
vices->setFactory(ServerUrlMiddleware::class, ServerUrlMiddlewareFactory::class);
imple:
ple[ServerUrlHelper::class] = $pimple->share(function ($container) {
return new ServerUrlHelper();
ple[ServerUrlMiddleware::class] = $pimple->share(function ($container) {
$factory = new ServerUrlMiddlewareFactory();
return $factory($container);
ura.Di:
tainer->set(ServerUrlHelper::class, $container->lazyNew(ServerUrlHelper::class));
tainer->set(ServerUrlMiddlewareFactory::class, $container->lazyNew(ServerUrlMiddlewareFactory::class));
tainer->set(
ServerUrlMiddleware::class,
$container->lazyGetCall(ServerUrlMiddlewareFactory::class, '__invoke', $container)
To register the ServerUrlMiddleware
in your middleware pipeline:
Zend\Expressive\Helper\ServerUrlMiddleware;
o this early, before piping other middleware or routes:
->pipe(ServerUrlMiddleware::class);
.. */
->pipeRoutingMiddleware();
->pipeDispatchMiddleware();
r use configuration:
'middleware_pipeline' => [
[
'middleware' => ServerUrlMiddleware::class,
'priority' => PHP_INT_MAX,
],
],
The following dependency configuration will work for all three when using the Expressive skeleton:
rn [
'dependencies' => [
'invokables' => [
ServerUrlHelper::class => ServerUrlHelper::class,
],
'factories' => [
ServerUrlMiddleware::class => ServerUrlMiddlewareFactory::class,
],
],
'middleware_pipeline' => [
[
'middleware' => ServerUrlMiddleware::class,
'priority' => PHP_INT_MAX,
],
],
Compose the helper in your middleware (or elsewhere), and then use it to generate URI paths:
Zend\Expressive\Helper\ServerUrlHelper;
s FooMiddleware
private $helper;
public function __construct(ServerUrlHelper $helper)
{
$this->helper = $helper;
}
public function __invoke($request, $response, callable $next)
{
$response = $response->withHeader(
'Link',
$this->helper->generate() . '; rel="self"'
);
return $next($request, $response);
}
You can use the methods generate()
and __invoke()
interchangeably (i.e., you
can use the helper as a function if desired). The signature is:
tion ($path = null) : string
Where:
$path
, when provided, can be a string path to use to generate a URI.One aspect of PSR-7 is that it allows you to parse the raw request body, and
then create a new instance with the results of parsing that later processes can
fetch via getParsedBody()
. It does not provide any actual facilities for
parsing, which means you must write middleware to do so.
This package provides such facilities via Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware
.
By default, this middleware will detect the following content types:
application/x-www-form-urlencoded
(standard web-based forms, without file
uploads)application/json
, application/*+json
(JSON payloads)You can register it manually:
Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
->pipe(BodyParamsMiddleware::class);
or, if using Expressive, as pipeline middleware:
onfig/autoload/middleware-pipeline.global.php
Zend\Expressive\Helper;
rn [
'dependencies' => [
'invokables' => [
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
/* ... */
],
'factories' => [
/* ... */
],
],
'middleware_pipeline' => [
[
'middleware' => Helper\BodyParams\BodyParamsMiddleware::class,
'priority' => 1000,
],
'routing' => [
/* ... */
],
],
If you want to intercept and parse other payload types, you can add strategies
to the middleware. Strategies implement Zend\Expressive\Helper\BodyParams\StrategyInterface
:
space Zend\Expressive\Helper\BodyParams;
Psr\Http\Message\ServerRequestInterface;
rface StrategyInterface
/**
* Match the content type to the strategy criteria.
*
* @param string $contentType
* @return bool Whether or not the strategy matches.
*/
public function match($contentType);
/**
* Parse the body content and return a new response.
*
* @param ServerRequestInterface $request
* @return ServerRequestInterface
*/
public function parse(ServerRequestInterface $request);
You then register them with the middleware using the addStrategy()
method:
yParams->addStrategy(new MyCustomBodyParamsStrategy());
To automate the registration, we recommend writing a factory for the
BodyParamsMiddleware
, and replacing the invokables
registration with a
registration in the factories
section of the middleware-pipeline.config.php
file:
Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
s MyCustomBodyParamsStrategyFactory
public function __invoke($container)
{
$bodyParams = new BodyParamsMiddleware();
$bodyParams->addStrategy(new MyCustomBodyParamsStrategy());
return $bodyParams;
}
n config/autoload/middleware-pipeline.config.php:
Zend\Expressive\Helper;
rn [
'dependencies' => [
'invokables' => [
// Remove this line:
Helper\BodyParams\BodyParamsMiddleware::class => Helper\BodyParams\BodyParamsMiddleware::class,
/* ... */
],
'factories' => [
// Add this line:
Helper\BodyParams\BodyParamsMiddleware::class => MyCustomBodyParamsStrategy::class,
/* ... */
],
],
If you do not want to use the default strategies (form data and JSON), you can
clear them from the middleware using clearStrategies()
:
yParamsMiddleware->clearStrategies();
Note: if you do this, all strategies will be removed! As such, we recommend doing this only immediately before registering any custom strategies you might be using.
In some cases, you may want to include an explicit Content-Length
response
header, without having to inject it manually. To facilitate this, we provide
Zend\Expressive\Helper\ContentLengthMiddleware
.
This middleware delegates the request, and operates on the returned response. It
will return a new response with the Content-Length
header injected under the
following conditions:
Content-Length
header is already present ANDTo register it in your application, you will need to do two things: register the middleware with the container, and register the middleware in either your application pipeline, or within routed middleware.
To add it to your container, add the following configuration:
n a `config/autoload/*.global.php` file, or a `ConfigProvider` class:
Zend\Expressive\Helper;
rn [
'dependencies' => [
'invokables' => [
Helper\ContentLengthMiddleware::class => Helper\ContentLengthMiddleware::class,
],
],
To register it as pipeline middleware to execute on any request:
n `config/pipeline.php`:
Zend\Expressive\Helper;
->pipe(Helper\ContentLengthMiddleware::class);
To register it within a routed middleware pipeline:
n `config/routes.php`:
Zend\Expressive\Helper;
->get('/download/tarball', [
Helper\ContentLengthMiddleware::class,
Download\Tarball::class,
download-tar');
See the zend-expressive documentation tree, or browse online at https://docs.zendframework.com/zend-expressive/features/helpers/intro/