mehr-it/eli_dispatcher

基于PSR-7和PSR-15标准的PHP应用程序的灵活轻量级请求调度器(和发射器)

1.0.1 2020-05-25 20:23 UTC

This package is auto-updated.

Last update: 2024-09-21 23:38:00 UTC


README

快速轻量级请求调度器(和发射器)用于使用PSR-7和PSR-15的PHP应用程序。

基本概念

调度器可以使用自定义的PSR-15请求处理器来解析请求。任何PSR-15中间件(或闭包)都可以添加到处理链中。

请求从全局变量(或作为参数传递)创建,由中间件处理,交给请求处理器,然后发射(或返回)。

基本用法

以下示例展示了使用调度器的基本和最常见方式

(new Dispatcher())
	->middleware(new SessionMiddleware())
	->middleware(function($request, $next) {
		// implement middleware code here
	})
	->middleware(function($request) {
		// return response
	})
	->dispatch();

创建一个调度器实例,添加中间件,并发送请求。您可能注意到示例中没有请求处理器。实际上,如果您实现了一个不调用“下一个”而是返回响应的中间件,您就不需要它。这意味着任何中间件都可以作为请求处理器。

添加中间件

如果您想添加用于请求处理的中间件,您可以传递一个PSR-15中间件

$dispatcher->middleware(new MyMiddleware())

或一个可调用的函数,例如闭包

$dispatcher->middleware(function(ServerRequestInterface $request, RequestHandlerInterface $next) {

	// this middleware does nothing, only return the 
	// response generated by the next handler
	return $next->handle();
 
})

中间件,即使是闭包也必须始终返回一个响应。但是,是否调用下一个处理程序并处理其响应或生成一个不调用任何进一步处理程序的响应,取决于中间件。

请求处理器

如上所述,您不必使用请求处理器。实际上,请求处理器是一个不能链式的中间件。因此,您不能做任何中间件做不到的事情。

然而,请求处理链需要一个终点。默认情况下,请求处理器返回一个没有主体的404响应被附加到链中。

如果您想更改此行为,您可以设置自己的请求处理器

$dispatcher->handler(new RequestHandler());

传递请求

如果没有参数调用dispatch()方法,请求将从PHP的全局变量中捕获。

$dispatcher->dispatch();

但是,您也可以传递一个自定义的PSR-7服务器请求实例进行调度

$dispatcher->dispatch($serverRequest);

返回响应

默认情况下,调度器发射生成的响应。如果您不想发射响应,只想返回它,可以将第二个参数设置为false

$response = dispatcher->dispatch(null, false); 

终止处理器

有时在请求被发射后,还有一些工作要做。常见的例子包括写入日志条目或持久化会话数据。

在将请求发送到客户端之后执行这些操作可以大大提高响应时间。

要注册在请求发送后要调用的处理器,您可以使用onTerminate方法

$dispatcher->onTerminate(function($request, $response) {
	
	// implement your code here
	 
});

通常,中间件需要添加终止处理器。由于中间件不能自己访问当前调度器实例,因此可以静态调用onTerminate()方法

Dispatcher::onTerminate($handler, true);

静态调用仅在调度期间是可能的,并且被转发到当前正在调度的调度器实例。

通常,中间件会将第二个参数设置为true,这将导致处理程序只被调用一次。这允许重用调度器并只为每个请求添加终止处理器。

流式响应

默认情况下,调度器将响应分块“流”到客户端。您可以使用sendBuffer()方法配置块大小,甚至可以通过传递发送缓冲区大小0来禁用流

$dispatcher->sendBuffer(1024 * 1024);

Dispatcher::sendBuffer(0);

当启用流式传输时,客户端可以请求响应的一部分。

然而,您应该在响应中添加 accept-ranges: bytes 报头,以便向客户端指示此功能。

内容长度

如果已知响应体的大小,则调度器将自动添加 content-length 报头(如果尚未存在)。

引导脚本

如果您需要根据执行环境配置不同的中间件,引导脚本非常方便。

您可以将当前环境的引导脚本传递给调度器构造函数。在引导脚本中,您可以配置调度器。

// index.php

if (/* condition* /)
	$bootScript = 'local.php';
else
	$bootScript = 'production.php';
	
(new Dispatcher($bootScript))->disptach();

引导脚本可以通过 $dispatcher 变量访问调度器实例并对其进行配置。

// local.php

$dispatcher->middleware(/* ... */);

有时中间件需要动态注入其他中间件。您可以使用 Chain 类轻松创建中间件处理链。请参见以下示例。

$dispatcher->middleware(function($request, $next) {

	if (/* ... */) {
		$chain = new Chain([
			new MiddlewareA(),
			new MiddlewareB(),
		], $next);
	}
	else {
		$chain = new Chain([
			new MiddlewareC(),
			function($request, $next) {
				/* ... */
			},
		], $next);
	}
	
	return $chain->handle($request);
});