原理
[外链图片转存中…(img-xFMkrOKR-1649730655060)]
加载顺序
全局中间件 -> 类中间件 -> 方法中间件
定义方式
-
全局定义
在
config/autoload/middleware.php中
定义全局中间件, 其中key的值对应的是server.php中的servers中定义的协议名称name, 表示在对应的协议上使用不同的全局中间件, 示例:[外链图片转存中…(img-bdkSS35x-1649730655060)]
-
类中定义
使用@Middleware或者@Middlewares引入多个中间件,如:/** * Desc: * Created By wujingfeng, at 2022/4/12 10:05 * # 单个引入 * @Middleware(Scjc\Lib\Middleware\HttpTraceMiddleware::class) * # 多个引入 * @Middlewares( * @Middleware(Scjc\Lib\Middleware\LogMiddleware::class), * @Middleware(Hyperf\Validation\Middleware\ValidationMiddleware::class), * ) */ class IndexController extends AbstractController{}
-
方法上定义
和类定义一致, 只不过类上的中间件是作用于类中所有方法, 而方法上定义的中间件只作用于本方法, 对类中的其他方法无效 -
在路由文件(routes.php)中使用
- 在路由定义时, 支持第三个参数, 用于描述该请求是否需要使用中间件,
- 路由文件定义时, 也支持定义在路由分组上, 表示该分组下的所有方法都需要使用中间件
-
示例:```
Router::addGroup( '/dashboard', function () { Router::addGroup('/order', function () { Router::post("/gerOrderTrend", [ \App\Controller\OrderController::class, 'gerOrderTrend' ]); Router::post("/getOrderRankTopN", [ \App\Controller\OrderController::class, 'getOrderRankTopN' ], # 单个方法请求上定义中间件 [\Scjc\Lib\Middleware\LogMiddleware::class]); }); }, # 全组中间件 ['middleware' => [AuthMiddleware::class]] );
-
全局更改请求或响应对象
虽然请求体和响应体会在中间件中进行传递, 但通过查看源码可知, 中间件中的请求体是通过getRequest()方法从协程上下文获取的, 因此如果需要对请求体进行修改, 则需要将修改后的内容也存放到协程中
响应体亦如此,
示例:
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
// $request 和 $response 为修改后的对象
$request = \Hyperf\Utils\Context::set(ServerRequestInterface::class, $request);
$response = \Hyperf\Utils\Context::set(ResponseInterface::class, $response);