> 中間件主要用于Controller的攔截處理,基于洋蔥模式,如下圖

> 執行順序:Request -> Middleware 1 -> Middleware 2 -> Middleware 3 -> Middleware 2 -> Middleware 1 -> Response
> 中間件有三種類型,他們的順序:`全局中間件 -> 類級別中間件 -> 方法級別中間件`
[TOC]
## 全局中間件
> 配置文件`/config/autoload/middlewares.php`
~~~
return [
// http 對應 config/autoload/server.php 內每個 server 的 name 屬性對應的值,該配置僅應用在該 Server 中
'http' => [
// 數組內配置您的全局中間件,順序根據該數組的順序
YourMiddleware::class
],
];
~~~
## 定義局部中間件
### 配置文件方式
> 配置文件`/config/routes.php`
~~~
use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Router\Router;
// 每個路由定義方法都可接收一個 $options 參數
Router::get('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::post('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
Router::addRoute(['GET', 'POST', 'HEAD'], '/index', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
// 該 Group 下的所有路由都將應用配置的中間件
Router::addGroup(
'/v2', function () {
Router::get('/index', [\App\Controller\IndexController::class, 'index']);
},
['middleware' => [FooMiddleware::class]]
);
~~~
### 注解方式
> 注解里含有Middlewares和Middleware兩種注解,Middlewares可包含多個Middleware
#### 類級別中間件
~~~
namespace App\Controller;
use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
/**
* @AutoController()
* @Middleware(FooMiddleware::class)
*/
class IndexController
{
public function index() {
return 'Hello Hyperf.';
}
}
~~~
#### 方法級別中間件
> 類級別上的中間件會優先于方法級別的中間件
~~~
namespace App\Controller;
use App\Middleware\BarMiddleware;
use App\Middleware\FooMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
/**
* @AutoController()
* @Middlewares({
* @Middleware(FooMiddleware::class)
* })
*/
class IndexController
{
/**
* @Middlewares({
* @Middleware(BarMiddleware::class)
* })
*/
public function index() {
return 'Hello Hyperf.';
}
}
~~~
## 生成中間件
~~~
php ./bin/hyperf.php gen:middleware Auth/FooMiddleware
~~~
~~~
declare(strict_types=1);
namespace App\Middleware\Auth;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class FooMiddleware implements MiddlewareInterface
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var RequestInterface
*/
protected $request;
/**
* @var HttpResponse
*/
protected $response;
public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
{
$this->container = $container;
$this->response = $response;
$this->request = $request;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 根據具體業務判斷邏輯走向,這里假設用戶攜帶的token有效
$isValidToken = true;
if ($isValidToken) {
return $handler->handle($request);
}
return $this->response->json(
[
'code' => -1,
'data' => [
'error' => '中間里驗證token無效,阻止繼續向下執行',
],
]
);
}
}
~~~