安装,
一般开发都是windows,所以用虚拟机或docker
利用
启动
假如出现端口被占用,下面的处理方法
2. kill掉
热更新
Watcher 组件除了办理上述启动问题,还提供了文件修改后立马重启的功能。
安装
- composer require hyperf/watcher --dev
复制代码 发布配置
- php bin/hyperf.php vendor:publish hyperf/watcher
复制代码 发布配置后在目录config/autoload/下自动生成watcher.php文件
配置 默认值 备注
driverScanFileDriver默认定时扫描文件驱动binPHP_BINARY用于启动服务的脚本watch.dirapp, config监听目录watch.file.env监听文件watch.interval2000扫描隔断(毫秒)ext.php, .env监听目录下的文件扩展名 启动
hyperf框架可以利用hyperf/watcher举行热更新操纵,不消每次修改完代码都重启服务
注意:
利用php bin/hyperf.php server:watch
这个命令后,php bin/hyperf.php start 这个命令将废弃
- php bin/hyperf.php server:watch
复制代码 路由
配置文件路由
- <?php
- use Hyperf\HttpServer\Router\Router;
- // 此处代码示例为每个示例都提供了三种不同的绑定定义方式,实际配置时仅可采用一种且仅定义一次相同的路由
- // 设置一个 GET 请求的路由,绑定访问地址 '/get' 到 App\Controller\IndexController 的 get 方法
- Router::get('/get', 'App\Controller\IndexController::get');
- Router::get('/get', 'App\Controller\IndexController@get');
- Router::get('/get', [\App\Controller\IndexController::class, 'get']);
- // 设置一个 POST 请求的路由,绑定访问地址 '/post' 到 App\Controller\IndexController 的 post 方法
- Router::post('/post', 'App\Controller\IndexController::post');
- Router::post('/post', 'App\Controller\IndexController@post');
- Router::post('/post', [\App\Controller\IndexController::class, 'post']);
- // 设置一个允许 GET、POST 和 HEAD 请求的路由,绑定访问地址 '/multi' 到 App\Controller\IndexController 的 multi 方法
- Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', 'App\Controller\IndexController::multi');
- Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', 'App\Controller\IndexController@multi');
- Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', [\App\Controller\IndexController::class, 'multi']);
复制代码 路由组
- Router::addGroup('/user',function (){
- Router::get('/index', 'App\Controller\UserController::index');
- Router::post('/create', 'App\Controller\UserController::createUser');
- Router::put('/update', 'App\Controller\UserController::update');
- Router::delete('/delete', 'App\Controller\UserController::delete');
- });
复制代码 必填参数
我们可以对 $uri 举行一些参数界说,通过 {} 来声明参数,如 /user/{id} 则声明了 id 值为一个必填参数。
可选参数
偶然间您大概会希望这个参数是可选的,您可以通过[]来声明中括号内的参数为一个可选参数,如 /user/[{id}]。
校验参数
您也可以利用正则表达式对参数举行校验,以下是一些例子
- use Hyperf\HttpServer\Router\Router;
- // 可以匹配 /user/42, 但不能匹配 /user/xyz
- Router::addRoute('GET', '/user/{id:\d+}', 'handler');
- // 可以匹配 /user/foobar, 但不能匹配 /user/foo/bar
- Router::addRoute('GET', '/user/{name}', 'handler');
- // 也可以匹配 /user/foo/bar as well
- Router::addRoute('GET', '/user/{name:.+}', 'handler');
- // 这个路由
- Router::addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler');
- // 等同于以下的两个路由
- Router::addRoute('GET', '/user/{id:\d+}', 'handler');
- Router::addRoute('GET', '/user/{id:\d+}/{name}', 'handler');
- // 多个可选的嵌套也是允许的
- Router::addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler');
- // 这是一条无效的路由, 因为可选部分只能出现在最后
- Router::addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler');
复制代码 注解路由
例如:
- <?php
- /**
- * OrderController.php
- *
- * Created on Orders-11:19
- * Created by xxp 332410549@qq.com
- */
- namespace App\Controller;
- use Hyperf\HttpServer\Annotation\Controller;
- use Hyperf\HttpServer\Annotation\GetMapping;
- use Hyperf\HttpServer\Contract\RequestInterface;
- /**
- * @Controller(prefix="order")
- */
- class OrderController extends AbstractController
- {
- /**
- * @GetMapping(path="index")
- */
- public function index(RequestInterface $request)
- {
- return 'OrderController'.$request->input('id');
- }
- }
复制代码 访问地点
- http://hyperf.demos.xp:9501/order/index
复制代码 HTTP 非常
在路由匹配不到路由时,如 路由找不到(404)、请求方法不答应(405) 等 HTTP 非常,Hyperf 会同一抛出一个 Hyperf\HttpMessage\Exception\HttpException 非常类的子类,
您需要通过 ExceptionHandler 机制来管理这些非常并做对应的响应处理,默认环境下可以直接利用组件提供的 Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler 来举行非常捕获处理,注意这个非常处理器需要您自行配置到 config/autoload/exceptions.php 配置文件中去,并保障多个非常处理器之间的序次链路是正确的。
当您需要对 路由找不到(404)、请求方法不答应(405) 等 HTTP 非常环境的响应举行自界说处理时,您可直接根据 HttpExceptionHandler 的代码实现您自己的非常处理器,并配置您自己的非常处理器。关于非常处理器的逻辑和利用说明,可具体查阅 非常处理
非常处理器
在 Hyperf 里,业务代码都运行在 Worker 进程 上,也就意味着一旦恣意一个请求的业务存在没有捕获处理的非常的话,都会导致对应的 Worker 进程 被停止退出,这对服务而言也是不能接受的,捕获非常并输出公道的报错内容给客户端也是更加友好的。
我们可以通过对各个 server 界说不同的 非常处理器(ExceptionHandler),一旦业务流程存在没有捕获的非常,都会被通报到已注册的 非常处理器(ExceptionHandler) 去处理。
自界说一个非常处理
1. 通过配置文件注册非常处理器
config/autoload/exceptions.php 文件
- <?php
- // config/autoload/exceptions.php
- return [
- 'handler' => [
- 'http' => [
- Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
- App\Exception\Handler\AppExceptionHandler::class,
- App\Exception\Handler\FooExceptionHandler::class,
- ],
- ],
- ];
复制代码 2. 界说非常处理器
app/Exception/Handler/FooExceptionHandler.php
- <?php
- /**
- * FooExceptionHandler.php
- *
- * Created on ExceptionHandler -13:35
- * Created by xxp 332410549@qq.com
- */
- namespace App\Exception\Handler;
- use App\Exception\FooException;
- use Hyperf\ExceptionHandler\ExceptionHandler;
- use Hyperf\HttpMessage\Stream\SwooleStream;
- use Psr\Http\Message\ResponseInterface;
- use Throwable;
- class FooExceptionHandler extends ExceptionHandler
- {
- /**
- * @inheritDoc
- */
- public function handle(Throwable $throwable, ResponseInterface $response)
- {
- // 判断被捕获到的异常是希望被捕获的异常
- if ($throwable instanceof FooException) {
- // 格式化输出
- $data = json_encode([
- 'code' => $throwable->getCode(),
- 'message' => $throwable->getMessage(),
- ], JSON_UNESCAPED_UNICODE);
- // 阻止异常冒泡
- $this->stopPropagation();
- return $response->withStatus(500)->withBody(new SwooleStream($data));
- }
- // 交给下一个异常处理器
- return $response;
- }
- /**
- * @inheritDoc
- */
- public function isValid(Throwable $throwable): bool
- {
- return true;
- }
- }
复制代码 3. 界说非常类
app/Exception/FooException.php
- <?php
- /**
- * FooException.php
- *
- * Created on FooException-13:40
- * Created by xxp 332410549@qq.com
- */
- namespace App\Exception;
- use Hyperf\Server\Exception\ServerException;
- class FooException extends ServerException
- {
- }
复制代码 4. 触发非常
- <?php
- /**
- * OrderController.php
- *
- * Created on Orders-11:19
- * Created by xxp 332410549@qq.com
- */
- namespace App\Controller;
- use App\Exception\FooException;
- use Hyperf\HttpServer\Annotation\Controller;
- use Hyperf\HttpServer\Annotation\GetMapping;
- use Hyperf\HttpServer\Contract\RequestInterface;
- /**
- * @Controller(prefix="order")
- */
- class OrderController extends AbstractController
- {
- /**
- * @GetMapping(path="index")
- */
- public function index(RequestInterface $request)
- {
- try {
- $data = [
- 'code' => 0,
- 'msg' => '获取成功',
- 'data' => [
- 'orders' => '订单列表'
- ]
- ];
- if (1) { // 如果没有数据,返回空数组
- throw new FooException('自定义异常');
- }
- return $this->response->json($data);
- } catch (\Exception $e) {
- return $this->response->json(['code' => 1,'msg' => $e->getMessage()]);
- }
- }
- }
复制代码 检察办理
总结:
在上面这个例子,我们先假设 FooException 是存在的一个非常,以及假设已经完成了该处理器的配置,那么当业务抛出一个没有被捕获处理的非常时,就会根据配置的序次依次通报,整一个处理流程可以明白为一个管道,若前一个非常处理器调用 $this->stopPropagation() 则不再往后通报,若最后一个配置的非常处理器仍不对该非常举行捕获处理,那么就会交由 Hyperf 的默认非常处理器处理了。
Error 监听器
框架提供了 error_reporting() 错误级别的监听器 Hyperf\ExceptionHandler\Listener\ErrorExceptionHandler。
配置
在 config/autoload/listeners.php 中添加监听器
- <?php
- return [
- \Hyperf\ExceptionHandler\Listener\ErrorExceptionHandler::class
- ];
复制代码 抓取错误
则当出现类似以下的代码时会抛出 \ErrorException 非常
- public function index(RequestInterface $request)
- {
- try {
- $a = [];
- ($a[1]);
- return $this->response->json($data);
- } catch (\Throwable $e) {
- return $this->response->json(['code' => 1,'msg' => $e->getMessage() ."\n num:". $e->getLine()]);
- }
- }
复制代码 结果
中间件
原理图
中间件重要用于编织从 请求(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/autoload/middlewares.php ,配置如下:
- <?php
- return [
- // http 对应 config/autoload/server.php 内每个 server 的 name 属性对应的值,该配置仅应用在该 Server 中
- 'http' => [
- // 数组内配置您的全局中间件,顺序根据该数组的顺序
- YourMiddleware::class
- ],
- ];
复制代码 只需将您的全局中间件配置在该文件及对应的 Server Name 内,即该 Server 下的所有请求都会应用配置的全局中间件。
界说局部中间件
当我们有些中间件仅仅面向某些请求或控制器时,即可将其界说为局部中间件,可通过配置文件的方式界说或注解的方式。
通过配置文件界说
在利用配置文件界说路由时,您仅可通过配置文件来界说对应的中间件,局部中间件的配置将在路由配置上完成。
Hyperf\HttpServer\Router\Router 类的每个界说路由的方法的最后一个参数 $options 都将接收一个数组,可通过通报键值 middleware 及一个数组值来界说该路由的中间件,我们通过几个路由界说来演示一下:
- <?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::put('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
- Router::patch('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
- Router::delete('/', [\App\Controller\IndexController::class, 'index'], ['middleware' => [FooMiddleware::class]]);
- Router::head('/', [\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]]
- );
复制代码 通过注解界说
在通过注解界说路由时,您仅可通过注解的方式来界说中间件,对中间件的界说有两个注解,分别为:
#[Middleware] 注解为界说单个中间件时利用,在一个地方仅可界说一个该注解,不可重复界说
#[Middlewares] 注解为界说多个中间件时利用,在一个地方仅可界说一个该注解,然后通过在该注解内界说多个 #[Middleware] 注解实现多个中间件的界说
利用 #[Middleware] 注解时需 use Hyperf\HttpServer\Annotation\Middleware; 命名空间;
利用 #[Middlewares] 注解时需 use Hyperf\HttpServer\Annotation\Middlewares; 命名空间;
注意:必须共同 #[AutoController] 大概 #[Controller] 利用
界说单个中间件:
- <?php
- 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.';
- }
- }
复制代码 通过 #[Middlewares] 注解界说多个中间件:
- <?php
- 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([FooMiddleware::class, BarMiddleware::class])]
- class IndexController
- {
- public function index()
- {
- return 'Hello Hyperf.';
- }
- }
复制代码 界说方法级别的中间件
在通过配置文件的方式配置中间件时界说到方法级别上很简朴,那么要通过注解的情势界说到方法级别呢?您只需将注解直接界说到方法上即可。
类级别上的中间件会优先于方法级别的中间件,我们通过代码来举例一下:
- <?php
- 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([FooMiddleware::class])]
- class IndexController
- {
- #[Middleware(BarMiddleware::class)]
- public function index()
- {
- return 'Hello Hyperf.';
- }
- }
复制代码 中间件相干的代码
生成中间件
- php ./bin/hyperf.php gen:middleware Auth/FooMiddleware
复制代码- <?php
- 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
- {
- protected ContainerInterface $container;
- protected RequestInterface $request;
- protected HttpResponse $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无效,阻止继续向下执行',
- ],
- ]
- );
- }
- }
复制代码 中间件的执行序次为 FooMiddleware -> BarMiddleware。
中间件的执行序次
我们从上面可以相识到总共有 3 种级别的中间件,分别为 全局中间件、类级别中间件、方法级别中间件,假如都界说了这些中间件,执行序次为:全局中间件 -> 类级别中间件 -> 方法级别中间件。
在>=3.0.34的版本中,新增了优先级的配置,可以在配置方法、路由中间件的时间改变中间件的执行序次,优先级越高,执行序次越靠前。
// 全局中间件配置文件 middleware.php
- return [
- 'http' => [
- YourMiddleware::class,
- YourMiddlewareB::class => 3,
- ],
- ];
- Copy to clipboardErrorCopied
- // 路由中间件配置
- Router::addGroup(
- '/v2', function () {
- Router::get('/index', [\App\Controller\IndexController::class, 'index']);
- },
- [
- 'middleware' => [
- FooMiddleware::class,
- FooMiddlewareB::class => 3,
- ]
- ]
- );
复制代码 // 注解中间件配置
- #[AutoController]
- #[Middleware(FooMiddleware::class)]
- #[Middleware(FooMiddlewareB::class, 3)]
- #[Middlewares([FooMiddlewareC::class => 1, BarMiddlewareD::class => 4])]
- class IndexController
- {
-
- }
复制代码 全局更改请求和响应对象
首先,在协程上下文内是有存储最原始的 PSR-7 请求对象 和 响应对象 的,且根据 PSR-7 对相干对象所要求的 不可变性(immutable),也就意味着我们在调用 $response = $response->with***() 所调用得到的 $response,并非为改写原对象,而是一个 Clone 出来的新对象,也就意味着我们储存在协程上下文内的 请求对象 和 响应对象 是不会改变的,那么当我们在中间件内的某些逻辑改变了 请求对象 或 响应对象,而且我们希望对后续的 非通报性的 代码再获取改变后的 请求对象 或 响应对象,那么我们便可以在改变对象后,将新的对象设置到上下文中,如代码所示:
- use Psr\Http\Message\ResponseInterface;
- use Psr\Http\Message\ServerRequestInterface;
- // $request 和 $response 为修改后的对象
- $request = \Hyperf\Context\Context::set(ServerRequestInterface::class, $request);
- $response = \Hyperf\Context\Context::set(ResponseInterface::class, $response);
复制代码 自界说 CoreMiddleWare 的举动
默认环境下,Hyperf 在处理路由找不到或 HTTP 方法不答应时,即 HTTP 状态码为 404、405 的时间,是由 CoreMiddleware 直接处理并返回对应的响应对象的,得益于 Hyperf 依靠注入的设计,您可以通过更换对象的方式来把 CoreMiddleware 指向由您自己实现的 CoreMiddleware 去。
比如我们希望界说一个 App\Middleware\CoreMiddleware 类来重写默认的举动,我们可以先界说一个 App\Middleware\CoreMiddleware 类如下,这里我们仅以 HTTP Server 为例,其它 Server 也可采用同样的做法来达到同样的目的。
- <?php
- declare(strict_types=1);
- namespace App\Middleware;
- use Hyperf\Contract\Arrayable;
- use Hyperf\HttpMessage\Stream\SwooleStream;
- use Psr\Http\Message\ResponseInterface;
- use Psr\Http\Message\ServerRequestInterface;
- class CoreMiddleware extends \Hyperf\HttpServer\CoreMiddleware
- {
- /**
- * Handle the response when cannot found any routes.
- *
- * @return array|Arrayable|mixed|ResponseInterface|string
- */
- protected function handleNotFound(ServerRequestInterface $request)
- {
- // 重写路由找不到的处理逻辑
- return $this->response()->withStatus(404);
- }
- /**
- * Handle the response when the routes found but doesn't match any available methods.
- *
- * @return array|Arrayable|mixed|ResponseInterface|string
- */
- protected function handleMethodNotAllowed(array $methods, ServerRequestInterface $request)
- {
- // 重写 HTTP 方法不允许的处理逻辑
- return $this->response()->withStatus(405);
- }
- }
复制代码 然后再在 config/autoload/dependencies.php 界说对象关系重写 CoreMiddleware 对象:
- <?php
- return [
- Hyperf\HttpServer\CoreMiddleware::class => App\Middleware\CoreMiddleware::class,
- ];
复制代码 这里直接重写 CoreMiddleware 的做法需要在 1.1.0+ 版本上才有效,1.0.x 版本仍需要你再将 CoreMiddleware 的上层调用通过 DI 举行重写,然后更换 CoreMiddleware 的传值为您界说的中间件类。
常用中间件
跨域中间件
假如您需要在框架中办理跨域,则可以按照您的需求实现以下中间件
- <?php
- declare(strict_types=1);
- namespace App\Middleware;
- use Hyperf\Context\Context;
- use Psr\Http\Message\ResponseInterface;
- use Psr\Http\Message\ServerRequestInterface;
- use Psr\Http\Server\MiddlewareInterface;
- use Psr\Http\Server\RequestHandlerInterface;
- class CorsMiddleware implements MiddlewareInterface
- {
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
- {
- $response = Context::get(ResponseInterface::class);
- $response = $response->withHeader('Access-Control-Allow-Origin', '*')
- ->withHeader('Access-Control-Allow-Credentials', 'true')
- // Headers 可以根据实际情况进行改写。
- ->withHeader('Access-Control-Allow-Headers', 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization');
- Context::set(ResponseInterface::class, $response);
- if ($request->getMethod() == 'OPTIONS') {
- return $response;
- }
- return $handler->handle($request);
- }
- }
复制代码 实际上,跨域配置也可以直接挂在 Nginx 上。
- location / {
- add_header Access-Control-Allow-Origin *;
- add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
- add_header Access-Control-Allow-Headers 'DNT,Keep-Alive,User-Agent,Cache-Control,Content-Type,Authorization';
- if ($request_method = 'OPTIONS') {
- return 204;
- }
- }
复制代码 后置中间件
通常环境下,我们都是最后执行
return h a n d l e r − > h a n d l e ( handler->handle( handler−>handle(request);
Copy to clipboardErrorCopied
所以,相称于是前置中间件,假如想要让中间件逻辑后置,其实只需要更换一下执行序次即可。
- <?php
- declare(strict_types=1);
- namespace App\Middleware;
- use Hyperf\HttpServer\Contract\RequestInterface;
- 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 OpenApiMiddleware implements MiddlewareInterface
- {
- public function __construct(protected ContainerInterface $container)
- {
- }
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
- {
- // TODO: 前置操作
- try{
- $result = $handler->handle($request);
- } finally {
- // TODO: 后置操作
- }
- return $result;
- }
- }
复制代码 实践
中间件文件
- <?php
- declare(strict_types=1);
- namespace App\Middleware\Auth;
- use Psr\Container\ContainerInterface;
- use Psr\Http\Message\ResponseInterface;
- use Psr\Http\Server\MiddlewareInterface;
- use Psr\Http\Message\ServerRequestInterface;
- use Psr\Http\Server\RequestHandlerInterface;
- use Hyperf\HttpServer\Contract\RequestInterface;
- use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
- 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
- {
- $isValidToken = true;
- if ($isValidToken) {
- return $handler->handle($request);
- }
- return $this->response->json(
- [
- 'code' => -1,
- 'data' => [
- 'error' => '中间件验证token无效,阻止继续向下执行 ',
- ],
- ]
- );
- }
- }
复制代码 $isValidToken 根据具体业务来判断
假如为真,则放行
假如为假,则阻断
中间件调用
- <?php
- /**
- * Message.php
- *
- * Created on Message-15:28
- * Created by xxp 332410549@qq.com
- */
- namespace App\Controller;
- use Hyperf\HttpServer\Annotation\AutoController;
- use App\Controller\AbstractController;
- use Hyperf\HttpServer\Annotation\Middleware;
- use App\Middleware\Auth\FooMiddleware;
- /**
- * @AutoController()
- * @Middleware(FooMiddleware::class)
- */
- class MessageController extends AbstractController
- {
- public function index()
- {
- return 'message';
- }
- }
复制代码 结果
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |