# 中间件
这里的中间件指的是 "中间件模式",主要用于编织从 请求(Request)
到 响应(Response)
的整个流程。
# 原理
中间件主要用于编织从 请求(Request)
到 响应(Response)
的整个流程,通过对多个中间件的组织,使数据的流动按我们预定的方式进行,中间件的本质是一个 洋葱模型
,我们通过一个图来解释它:
图中的顺序为按照 Middleware 1 -> Middleware 2 -> Middleware 3
的顺序组织着,我们可以注意到当中间的横线穿过 内核
即 Middleware 3
后,又回到了 Middleware 2
,为一个嵌套模型,那么实际的顺序其实就是:
Request -> Middleware 1 -> Middleware 2 -> Middleware 3 -> Middleware 2 -> Middleware 1 -> Response
重点放在 核心
即 Middleware 3
,它是洋葱的分界点,分界点前面的部分其实都是基于 请求(Request)
进行处理,而经过了分界点时,内核
就产出了 响应(Response)
对象,也是 内核
的主要代码目标,在之后便是对 响应(Response)
进行处理了,内核
通常是由框架负责实现的,而其它的就由您来编排了。
# 定义全局中间件
全局中间件只可通过配置文件的方式来配置,配置文件位于 config/middleware.config.php
,配置如下:
<?php
declare(strict_types=1);
use app\middleware\DuplicateRequestMiddleware;
use app\middleware\ValidateMiddleware;
return [
DuplicateRequestMiddleware::class,
ValidateMiddleware::class
];
只需将您的全局中间件配置在该文件上,即该 Server
下的所有请求都会应用配置的全局中间件。
全局验证器中间件的实现:
<?php
namespace app\middleware;
use herosphp\core\HttpRequest;
use herosphp\core\MiddlewareInterface;
use herosphp\plugin\validate\Valid;
use herosphp\plugin\validate\Validate;
use herosphp\plugin\validate\ValidateException;
use herosphp\WebApp;
class ValidateMiddleware implements MiddlewareInterface
{
/**
* @throws \ReflectionException
*/
public function process(HttpRequest $request, callable $handler)
{
$reflectionMethod = new \ReflectionMethod(WebApp::$_targetController, WebApp::$_targetMethod);
$reflectionAttributes = $reflectionMethod->getAttributes(Valid::class);
if ($reflectionAttributes) {
foreach ($reflectionAttributes as $validAttribute) {
/** @var Valid $methodValidInstance */
$methodValidInstance = $validAttribute->newInstance();
$methodVInstance = new ($methodValidInstance->class);
if (!$methodVInstance instanceof Validate) {
throw new ValidateException("{$methodVInstance->class} must extend \\herosphp\\plugin\\validate\Validate");
}
$methodVInstance->scene($methodValidInstance->scene)->check([...$request->get(), ...$request->post()]);
}
}
return $handler($request);
}
}
# 定义局部中间件
当我们有些中间件仅仅面向某些请求或控制器时,即可将其定义为局部中间件。
在需要特定Controller中,重写public array $middlewares = [];
属性。
比如,我们需要对一些路由需要进行授权才能访问。
# 1. 新建一个 AuthenticationController
<?php
declare(strict_types=1);
namespace app\modules\admin\action\uc;
use app\modules\admin\middlewares\AuthenticationMiddleware;
use app\modules\admin\middlewares\OperateLogMiddleware;
use app\modules\admin\model\LoginAdmin;
use app\modules\admin\utils\LoginToSession;
use herosphp\core\BaseController;
use herosphp\WebApp;
// uc
class AbAuthenticationController extends BaseController
{
public array $middlewares = [
AuthenticationMiddleware::class // 认证 and 授权验证
];
protected LoginAdmin $loginAdmin;
/**
* @throws \ReflectionException
*/
public function __init()
{
parent::__init();
$this->loginAdmin = LoginToSession::getLoginAdmin(WebApp::$_request);
}
}
# 2. 所有需要登录的Controller 都可以继承该控制器,即可实现部分路由需要授权认证。
← Session 管理 命令行任务 →