Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'feature/helpers' into develop
Browse files Browse the repository at this point in the history
Forward port #210
  • Loading branch information
weierophinney committed Dec 4, 2015
2 parents fee2e69 + 026a5eb commit 75a2d06
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 59 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ Third release candidate.
system.
- [#81](https://github.com/zendframework/zend-expressive/pull/81) adds a
cookbook entry for creating 404 handlers.
- [#210](https://github.com/zendframework/zend-expressive/pull/210) adds a
documentation section on the new [zendframework/zend-expressive-helpers](https://github.com/zendframework/zend-expressive-helpers)
utilities.

### Deprecated

Expand Down
8 changes: 8 additions & 0 deletions doc/book/helpers/bookdown.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"title": "Helpers",
"content": [
{"Introduction": "intro.md"},
{"UrlHelper": "url-helper.md"},
{"ServerUrlHelper": "server-url-helper.md"}
]
}
21 changes: 21 additions & 0 deletions doc/book/helpers/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Helpers

Some tasks and features will be common to many if not all applications. For
those, Expressive provides *helpers*. These are typically utility classes that
may integrate features or simply provide standalone benefits.

Currently, these include:

- [UrlHelper](url-helper.md)
- [ServerUrlHelper](server-url-helper.md)

## Installation

If you started your project using the Expressive skeleton package, the helpers
are already installed.

If not, you can install them as follows:

```bash
$ composer require zendframework/zend-expressive-helpers
```
152 changes: 152 additions & 0 deletions doc/book/helpers/server-url-helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# 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.

## Usage

When you have an instance, use either its `generate()` method, or call the
instance as an invokable:

```php
// Using the generate() method:
$url = $helper->generate('/foo');

// is equivalent to invocation:
$url = $helper('/foo');
```

The helper is particularly useful when used in conjunction with the
[UrlHelper](url-helper.md), as you can then create fully qualified URIs for use
with headers, API hypermedia links, etc.:

```php
$url = $serverUrl($url('resource', ['id' => 'sha1']));
```

The signature for the ServerUrlHelper `generate()` and `__invoke()` methods is:

```php
function ($path = null) : string
```

Where:

- `$path`, when provided, can be a string path to use to generate a URI.

## Creating an instance

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:

- Register the `ServerUrlHelper` as a service in your container.
- Register the `ServerUrlMiddleware` as a service in your container.
- Register the `ServerUrlMiddleware` as pre_routing pipeline middleware.

The following examples demonstrate registering the services.

```php
use Zend\Expressive\Helper\ServerUrlHelper;
use Zend\Expressive\Helper\ServerUrlMiddleware;
use Zend\Expressive\Helper\ServerUrlMiddlewareFactory;

// zend-servicemanager:
$services->setInvokableClass(ServerUrlHelper::class, ServerUrlHelper::class);
$services->setFactory(ServerUrlMiddleware::class, ServerUrlMiddlewareFactory::class);

// Pimple:
$pimple[ServerUrlHelper::class] = $pimple->share(function ($container) {
return new ServerUrlHelper();
});
$pimple[ServerUrlMiddleware::class] = $pimple->share(function ($container) {
$factory = new ServerUrlMiddlewareFactory();
return $factory($container);
});

// Aura.Di:
$container->set(ServerUrlHelper::class, $container->lazyNew(ServerUrlHelper::class));
$container->set(ServerUrlMiddlewareFactory::class, $container->lazyNew(ServerUrlMiddlewareFactory::class));
$container->set(
ServerUrlMiddleware::class,
$container->lazyGetCall(ServerUrlMiddlewareFactory::class, '__invoke', $container)
);
```

To register the `ServerUrlMiddleware` as pre-routing pipeline middleware:

```php
use Zend\Expressive\Helper\ServerUrlMiddleware;

// Do this early, before piping other middleware or routes:
$app->pipe(ServerUrlMiddleware::class);

// Or use configuration:
// [
// 'middleware_pipeline' => [
// 'pre_routing' => [
// ['middleware' => ServerUrlMiddleware::class],
// ],
// ],
// ]
```

The following dependency configuration will work for all three when using the
Expressive skeleton:

```php
return [
'dependencies' => [
'invokables' => [
ServerUrlHelper::class => ServerUrlHelper::class,
],
'factories' => [
ServerUrlMiddleware::class => ServerUrlMiddlewareFactory::class,
],
],
'middleware_pipeline' => [
'pre_routing' => [
['middleware' => ServerUrlMiddleware::class],
],
],
]
```

> ## Skeleton configures helpers
>
> If you started your project using the Expressive skeleton package, the
> `ServerUrlHelper` and `ServerUrlMiddleware` factories are already registered
> for you, as is the `ServerUrlMiddleware` pre_routing pipeline middleware.
## Using the helper in middleware

Compose the helper in your middleware (or elsewhere), and then use it to
generate URI paths:

```php
use Zend\Expressive\Helper\ServerUrlHelper;

class 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);
}
}
```
130 changes: 130 additions & 0 deletions doc/book/helpers/url-helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# 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`.
If registered as a route result observer, and the route being used 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.

## Usage

When you have an instance, use either its `generate()` method, or call the
instance as an invokable:

```php
// Using the generate() method:
$url = $helper->generate('resource', ['id' => 'sha1']);

// is equivalent to invocation:
$url = $helper('resource', ['id' => 'sha1']);
```

The signature for both is:

```php
function ($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:
- If a `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.
- If a `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.
- If no `$params` are provided, and the `$routeName` matches the currently
matched route, then any matched parameters found will be used.
parameters found will be used.
- If no `$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:

- No `$routeName` is provided, and no `RouteResult` is composed.
- No `$routeName` is provided, a `RouteResult` is composed, but that result
represents a matching failure.
- The given `$routeName` is not defined in the router.

## Creating an instance

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:

```php
use Zend\Expressive\Helper\UrlHelper;
use Zend\Expressive\Helper\UrlHelperFactory;

// zend-servicemanager:
$services->setFactory(UrlHelper::class, UrlHelperFactory::class);

// Pimple:
$pimple[UrlHelper::class] = $pimple->share(function ($container) {
$factory = new UrlHelperFactory();
return $factory($container);
});

// Aura.Di:
$container->set(UrlHelperFactory::class, $container->lazyNew(UrlHelperFactory::class));
$container->set(
UrlHelper::class,
$container->lazyGetCall(UrlHelperFactory::class, '__invoke', $container)
);
```

The following dependency configuration will work for all three when using the
Expressive skeleton:

```php
return ['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.
> ## Skeleton configures helpers
>
> If you started your project using the Expressive skeleton package, the
> `UrlHelper` factory is already registered for you.
## Using the helper in middleware

Compose the helper in your middleware (or elsewhere), and then use it to
generate URI paths:

```php
use Zend\Expressive\Helper\UrlHelper;

class 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);
}
}
```
Loading

0 comments on commit 75a2d06

Please sign in to comment.