An open API service indexing awesome lists of open source software.

https://github.com/ellipsephp/dispatcher

Psr-15 middleware dispatcher implementation
https://github.com/ellipsephp/dispatcher

dispatcher middleware psr-15 request-handler

Last synced: about 1 month ago
JSON representation

Psr-15 middleware dispatcher implementation

Awesome Lists containing this project

README

          

# Dispatcher

This package provides a [Psr-15](https://www.php-fig.org/psr/psr-15/) dispatcher implementation.

**Require** php >= 7.0

**Installation** `composer require ellipse/dispatcher`

**Run tests** `./vendor/bin/kahlan`

- [Using a dispatcher](#using-a-dispatcher)
- [Middleware and request handler resolving](#middleware-and-request-handler-resolving)

## Using a dispatcher

This package provides an `Ellipse\Dispatcher` class allowing to process a Psr-7 request through a Psr-15 middleware queue (First in first out order) before handling it with a Psr-15 request handler in order to create a Psr-7 response.

It is basically a request handler decorator wrapping a middleware queue around a request handler. Its constructor takes two parameters:

- a request handler object implementing `Psr\Http\Server\RequestHandlerInterface`
- an array containing middleware objects implementing `Psr\Http\Server\MiddlewareInterface`

The `Dispatcher` itself implements `RequestHandlerInterface` so a response is produced by using its `->handle()` method with a request. It also means it can be used as the request handler of another `Dispatcher`. Also, The same `Dispatcher` can be used multiple times to handle as many requests as needed.

Finally when a value of the given middleware queue is not an implementation of `MiddlewareInterface` an `Ellipse\Dispatcher\Exceptions\MiddlewareTypeException` is thrown. [Factory decorators](#middleware-and-request-handler-resolving) can be used to resolve some type of values as middleware.

```php
handle($request);

// It can be used as the request handler of another dispatcher.
// Here the request goes through SomeMiddleware3, SomeMiddleware1, SomeMiddleware2 and SomeRequestHandler
(new Dispatcher($dispatcher, [new SomeMiddleware3]))->handle($request);

// Here a MiddlewareTypeException is thrown because 'something' is not a Psr-15 middleware.
new Dispatcher(new SomeRequestHandler, [new SomeMiddleware, 'something']);
```

The `Dispatcher` class also has a `->with()` method taking a `MiddlewareInterface` as parameter. It returns a new dispatcher with the given middleware wrapped around the current dispatcher. The new middleware will be the first processed by the new dispatcher:

```php
with(new SomeMiddleware3);

// Here the request goes through SomeMiddleware3, SomeMiddleware1, SomeMiddleware2 and SomeRequestHandler.
$response = $dispatcher->handle($request);

// It allows to create dispatchers from the outside-in if you like.
$dispatcher = new Dispatcher(new SomeRequestHandler);

$dispatcher = $dispatcher->with(new SomeMiddleware3);
$dispatcher = $dispatcher->with(new SomeMiddleware2);
$dispatcher = $dispatcher->with(new SomeMiddleware1);

// Here the request goes through SomeMiddleware1, SomeMiddleware2, SomeMiddleware3 and SomeRequestHandler.
$response = $dispatcher->handle($request);
```

## Middleware and request handler resolving

A common practice is to allow callables and class names registered in a container to be used as regular middleware/request handler.

For this purpose this package also provides an `Ellipse\DispatcherFactory` class implementing `Ellipse\DispatcherFactoryInterface`, allowing to produce `Dispatcher` instances. Its `__invoke()` method takes any value as request handler and an optional middleware queue. An `Ellipse\Dispatcher\Exceptions\RequestHandlerTypeException` is thrown when the given request handler is not an implementation of `RequestHandlerInterface`.

```php
handle($request);
```

Here is some ellipse packages providing resolvers for common resolving scenario:

- [ellipse/dispatcher-callable](https://github.com/ellipsephp/dispatcher-callable) allowing to use callables as Psr-15 middleware/request handlers
- [ellipse/dispatcher-container](https://github.com/ellipsephp/dispatcher-container) allowing to use Psr-15 middleware/request handler class names using a [Psr-11](https://www.php-fig.org/psr/psr-11/) container
- [ellipse/dispatcher-controller](https://github.com/ellipsephp/dispatcher-controller) allowing to use controller actions as Psr-15 request handlers using a [Psr-11](https://www.php-fig.org/psr/psr-11/) container

Here is an example of a class implementing `DispatcherFactoryInterface` in case you need to create a custom one:

```php
delegate = $delegate;
}

public function __invoke($handler, array $middleware = []): Dispatcher
{
// Replace the handler with a ResolvedRequestHandler when the request handler should be resolved.
$handler = $this->shouldResolveHandler($handler)
: new ResolvedRequestHandler($handler)
? $handler;

// Replace middleware with a ResolvedMiddleware when a middleware should be resolved.
$middleware = array_map(function ($middleware) {

return $this->shouldResolveMiddleware($middleware)
? new ResolvedMiddleware($middleware)
: $middleware;

}, $middleware);

// Delegate the dispatcher creation to the decorated factory.
return ($this->delegate)($handler, $middleware);
}

private shouldResolveHandler($handler): bool
{
// ...
}

private shouldResolveMiddleware($middleware): bool
{
// ...
}
}
```