椭圆 / 分发器
Requires
- php: >=7.0
- ellipse/handlers: ^1.0
- ellipse/type-errors: ^1.0
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- eloquent/phony-kahlan: ^1.0
- kahlan/kahlan: ^4.0
Suggests
- ellipse/dispatcher-callable: Allows to use callables as Psr-15 middleware/request handlers
- ellipse/dispatcher-composable: Allows to compose dispatcher
- ellipse/dispatcher-container: Allows to use Psr-15 middleware/request handler class names using a Psr-11 container
- ellipse/dispatcher-controller: Allows to use controller actions as Psr-15 request handlers using a Psr-11 container
README
本包提供了一种 Psr-15 分发器实现。
要求 php >= 7.0
安装 composer require ellipse/dispatcher
运行测试 ./vendor/bin/kahlan
使用分发器
该包提供了一个 Ellipse\Dispatcher
类,允许通过 Psr-15 中间件队列(先入先出顺序)处理 Psr-7 请求,然后再通过 Psr-15 请求处理器处理,以创建 Psr-7 响应。
它本质上是一个请求处理器装饰器,围绕请求处理器包装了一个中间件队列。其构造函数接受两个参数
- 一个实现了
Psr\Http\Server\RequestHandlerInterface
的请求处理器对象 - 一个包含实现了
Psr\Http\Server\MiddlewareInterface
的中间件对象的数组
该 Dispatcher
本身实现了 RequestHandlerInterface
,因此可以通过使用其 ->handle()
方法与请求一起产生一个响应。这也意味着它可以作为另一个 Dispatcher
的请求处理器使用。同样,同一个 Dispatcher
可以多次使用以处理所需数量的请求。
最后,如果给定中间件队列的值不是 MiddlewareInterface
的实现,将抛出 Ellipse\Dispatcher\Exceptions\MiddlewareTypeException
。可以使用 Factory decorators 来解析某些类型的值作为中间件。
<?php namespace App; use Ellipse\Dispatcher; // Create a dispatcher using two middleware and a request handler. $dispatcher = new Dispatcher(new SomeRequestHandler, [ new SomeMiddleware1, new SomeMiddleware2, ]); // Here the request goes through SomeMiddleware1, SomeMiddleware2 and SomeRequestHandler. $response = $dispatcher->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']);
Dispatcher
类还有一个 ->with()
方法,它接受一个 MiddlewareInterface
作为参数。它返回一个新的分发器,其中给定中间件围绕当前分发器包装。新中间件将首先由新分发器处理。
<?php namespace App; use Ellipse\Dispatcher; // Create a dispatcher with two middleware. $dispatcher = new Dispatcher(new SomeRequestHandler, [ new SomeMiddleware1, new SomeMiddleware2, ]); // Create a new dispatcher with a new middleware on the top of the middleware queue. $dispatcher = $dispatcher->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);
中间件和请求处理器解析
一种常见的做法是允许将可调用对象和容器中注册的类名用作常规中间件/请求处理器。
为此,该包还提供了一个实现 Ellipse\DispatcherFactoryInterface
的 Ellipse\DispatcherFactory
类,允许生产 Dispatcher
实例。它的 __invoke()
方法接受任何值作为请求处理器和一个可选的中间件队列。如果给定的请求处理器不是 RequestHandlerInterface
的实现,将抛出 Ellipse\Dispatcher\Exceptions\RequestHandlerTypeException
。
<?php namespace App; use Ellipse\DispatcherFactory; // Get a dispatcher factory. $factory = new DispatcherFactory; // Use the factory to create a new Dispatcher. $dispatcher = $factory(new SomeRequestHandler, [new SomeMiddleware]); // Here a RequestHandlerTypeException is thrown because 'something' is not a Psr-15 request handler. $dispatcher = $factory('something', [new SomeMiddleware]); // Here a MiddlewareTypeException is thrown by the Dispatcher class because 'something' is not a Psr-15 middleware. $dispatcher = $factory(new SomeRequestHandler, [new SomeMiddleware, 'something']);
该类本身并不很有用。DispatcherFactory
的目的是通过其他工厂装饰,在将给定值解析为 Psr-15 实现之前委托分发器创建。它是此类工厂装饰器(也称为解析器)的起点,确保在任何装饰器未能将任何值解析为 Psr-15 实现时,分发器创建失败。
以下是使用来自 ellipse/dispatcher-callable 包的 Ellipse\Dispatcher\CallableResolver
类解析可调用的示例
<?php namespace App; use Ellipse\DispatcherFactory; use Ellipse\Dispatcher\CallableResolver; // Get a decorated dispatcher factory. $factory = new CallableResolver(new DispatcherFactory); // A dispatcher using both callables and Psr-15 implementations can now be created. $middleware = function ($request, $handler) { // This callable behave like a Psr-15 middleware. }; $handler = function ($request) { // This callable behave like a Psr-15 request handler. }; // This works. $response = $factory($handler, [$middleware, new SomeMiddleware])->handle($request);
以下是提供常见解析场景解析器的某些椭圆包
- ellipse/dispatcher-callable 允许使用可调用对象作为 Psr-15 中间件/请求处理器
- ellipse/dispatcher-container 允许使用 Psr-15 中间件/请求处理器的类名,通过一个 Psr-11 容器
- ellipse/dispatcher-controller 允许使用控制器动作作为 Psr-15 请求处理器,通过一个 Psr-11 容器
以下是一个实现 DispatcherFactoryInterface
的类示例,如果您需要创建自定义的
<?php namespace App; use Ellipse\Dispatcher; use Ellipse\DispatcherFactoryInterface; class MyResolver implements DispatcherFactoryInterface { private $delegate; public function __construct(DispatcherFactoryInterface $delegate) { $this->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 { // ... } }