zendframework/zend-expressive-helpers

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

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

Helper classes for Expressive

Build Status Coverage Status

Helper classes for Expressive.

Installation

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:

Helpers Provided
UrlHelper

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:

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:

Each method will raise an exception if:

Base Path support

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.

ServerUrlHelper

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:

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:

BodyParams middleware

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:

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' => [
        /* ... */
    ],
],

Strategies

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,
        /* ... */
    ],
],

Removing the default strategies

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.

Content-Length middleware

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:

To 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');
Documentation

See the zend-expressive documentation tree, or browse online at https://docs.zendframework.com/zend-expressive/features/helpers/intro/


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.