vakata / middleman
PSR-15 中间件分发器。让我们停止试图使它变得复杂。
Requires
- php: >=7.0
- mindplay/readable: ^1
- psr/container: ^1.0
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- container-interop/container-interop: ^1.2
- mindplay/testies: ^0.2.0
- mockery/mockery: ^0.9.4
- phpunit/php-code-coverage: ^2.2
This package is auto-updated.
Last update: 2024-09-10 05:52:36 UTC
README
简单直观的 PSR-15 / PSR-7 中间件 分发器。
提供(可选)与符合 container-interop 的各种依赖注入容器的集成。
要升级到主要版本,请参阅 UPGRADING.md。
从 github.com/middlewares 可用不断增长的 PSR-15 中间件组件目录。
您可以通过使用中间件栈中的匿名函数来实现简单的中间件 "in place"。
use Psr\Http\Message\ServerRequestInterface; use Zend\Diactoros\Response; $dispatcher = new Dispatcher([ function (ServerRequestInterface $request, callable $next) { return $next($request); // delegate control to next middleware }, function (ServerRequestInterface $request) { return (new Response())->withBody(...); // abort middleware stack and return the response }, // ... ]); $response = $dispatcher->dispatch($request);
为了简单起见,Dispatcher
中的中间件栈是不可变的 - 如果您需要一个可操作的堆栈,可以使用 array
、ArrayObject
、SplStack
等等。
要实现可重用中间件组件,您应该实现 PSR-15 MiddlewareInterface。
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\ServerMiddleware\MiddlewareInterface; class MyMiddleware implements MiddlewareInteface { public function process(ServerRequestInterface $request, DelegateInterface $delegate) { // ... } }
如果您想与 DI 容器 集成,可以使用 ContainerResolver
- "resolver" 是一个可调用的函数,它应用于中间件堆栈中的每个元素,其签名如下:
function (string $name) : MiddlewareInterface
以下示例从 DI 容器动态获取中间件组件
$dispatcher = new Dispatcher( [ RouterMiddleware::class, ErrorMiddleware::class, ], new ContainerResolver($container) );
如果您想使 Dispatcher
深度集成到您选择的框架中,您可以将其实现为一个实现魔法 __invoke()
函数的类(如 ContainerResolver
所做) - 或者 "in place",作为一个具有匹配签名的匿名函数。
如果您想精确了解此组件的工作原理,整个组件只是一个包含几行代码的 类 - 如果您打算基于中间件构建下一个项目,您可以(并且应该)了解整个机制。
中间件?
中间件是一种强大且简单的控制设施。
如果您对中间件的概念不太熟悉,以下部分将提供一个基本概述。
简而言之,一个中间件组件是一个函数(或 MiddlewareInterface 实例),它接受一个传入的(PSR-7)RequestInterface
对象,并返回一个 ResponseInterface
对象。
它通过以下三种方式之一来完成:通过 假设、委托 或 共享 对响应对象的创建责任。
1. 假设责任
一个中间件组件通过创建和返回一个响应对象来 承担 责任,而不是将责任委托给堆栈中的下一个中间件。
use Zend\Diactoros\Response; function ($request, $next) { return (new Response())->withBody(...); // next middleware won't be run }
堆栈顶部的中间件具有完全绕过堆栈中更下面中间件的能力。
2. 委托责任
通过调用 $next
,堆栈顶部的中间件可以选择将创建响应的责任完全委托给堆栈中更下面的其他中间件组件。
function ($request, $next) { if ($request->getMethod() !== 'POST') { return $next($request); // run the next middleware } else { // ... } }
请注意,耗尽中间件堆栈将导致异常 - 假定堆栈上的最后一个中间件组件始终产生某种类型的响应,通常是 "404 未找到" 错误页面。
3. 共享责任
位于栈顶的中间件可以选择将创建响应的责任委托给栈中更低的中间件,然后在返回响应之前对返回的响应进行额外的修改。
function ($request, $next) { $result = $next($request); // run the next middleware return $result->withHeader(...); // then modify it's response }
位于栈顶的中间件组件最终拥有最多的控制权,因为它可以在返回之前覆盖响应对象的任何属性。