当前位置:首页 > Hyperf > 正文内容

Hyperf异常类,抛出异常并中断执行

陈杰2年前 (2020-12-09)Hyperf4078

在我们的传统的php框架中,我个人习惯代码需要分层的。


例如分为 Controller层,Service层,Model层。


Controller层就是做个参数接收啊,参数验证之类的事情,然后Service层才来做我们的业务逻辑,Model就是在数据库里面取数据。


在我的传统习惯中,如果Controller通过了数据验证,然后把参数交给Service处理,如果Service成功处理了,就return给Controller处理好的或者取到的数据,再通过reponse交给用户。


那么如果Service处理过程中,比如用户需要购买一件商品,商品id,购买数量都通过了验证了,但是钱不够了,那么就要return给controller错误信息,然后再由控制器去返回给用户,但是如果层级多了呢,一层一层返回是不是很恼火,这个业务错误就不能再这么搞了。就需要Service来做验证,告诉用户,余额不足。


在Laravel项目中我喜欢用一个

/**
* 终止程序并返回信息
*/
public static function returnError(string $msg = '操作失败', int $code = 400, $data = [])
{
   $data = [
       'msg'  => $msg,
       'code' => $code,
       'data' => $data
   ];
   exit(json_encode($data, JSON_UNESCAPED_UNICODE));
}


直接在Service中 returnError了,中断运行并返回错误信息,但是在Hyperf中,再用exit就不行了,找遍了百度都没找到前辈怎么处理的。


那还是算了,最爱的exit不能用了,还是老老实实的抛异常吧。。。。


下面上代码

新建一个MyException类

<?php
/**
* Author:陈杰
* Blog:http://blog.95shouyou.com
* Email:823380606@qq.com
* Git:https://gitee.com/chen95
* Date:2020/12/9 0009
* Time:12:35
*/

namespace App\Exception\Handler;

use Hyperf\Server\Exception\ServerException;


class MyException extends ServerException
{
   public $data = [];

   public function __construct($message = "操作失败", int $code = 400, $data = [])
   {
       $this->message = $message;
       $this->code    = $code;
       $this->data    = $data;
   }
}


然后再建一个BaseExceptionHandler类

<?php
/**
* Author:陈杰
* Blog:http://blog.95shouyou.com
* Email:823380606@qq.com
* Git:https://gitee.com/chen95
* Date:2020/12/9 0009
* Time:12:34
*/

namespace App\Exception\Handler;

use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;

use Throwable;

class BaseExceptionHandler extends ExceptionHandler
{
   public function handle(Throwable $throwable, ResponseInterface $response)
   {
       // 判断被捕获到的异常是希望被捕获的异常
       if ($throwable instanceof MyException) {
           // 格式化输出
           $data = json_encode([
               'code' => $throwable->getCode(),
               'msg'  => $throwable->getMessage(),
               'data' => $throwable->data,
           ], JSON_UNESCAPED_UNICODE);

           // 阻止异常冒泡
           $this->stopPropagation();
           return $response->withStatus(200)->withBody(new SwooleStream($data));
       }

       // 交给下一个异常处理器
       return $response;
   }

   /**
    * 判断该异常处理器是否要对该异常进行处理
    */
   public function isValid(Throwable $throwable): bool
   {
       return true;
   }
}


然后我们的通用抛出方法

public function returnError(string $msg = '操作失败', int $code = 400, $data = [])
{
   throw new MyException($msg, $code, $data);
}


这样在任何地方也可以直接中断运行并返回消息了,不用在Service中return给Controller让控制器做处理了。


当然你也可以建很多个异常类,不同的错误类型通过抛不同的异常类就行了。

但是一把梭更香,在我的世界里面,不是200通过就是400错误。没有其他的错误代码,至于错误原因,我又不做多语言,直接汉语告诉你了!!!!


最后还要去config里面配置一下

位于config/autoload/exceptions.php

<?php

declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link     https://www.hyperf.io
* @document https://hyperf.wiki
* @contact  group@hyperf.io
* @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
return [
   'handler' => [
       'http' => [
           \App\Exception\Handler\BaseExceptionHandler::class,
           \Hyperf\ExceptionHandler\Handler\WhoopsExceptionHandler::class
       ],
   ],
];


我引入了一个whoops异常,就是laravel用的那个漂亮的异常追踪界面

image.png


官方文档是这样介绍的,用了一样方式进行引入,结果返回给我的是这样的。。


image.png


这是通过ajax去取结果返回长成这样了,没有好看的界面了,我觉得应该是发起请求的request header中的accept的问题。因为直接通过浏览器去访问接口好看的界面又出来了,后面在研究一下吧

扫描二维码至手机访问

扫描二维码推送至手机访问。

版权声明:本文由何烦过虎溪发布,如需转载请注明出处。

转载请注明出处:http://95shouyou.com/?id=18

分享给朋友:

相关文章

Hyperf跨域问题的解决方案

Hyperf跨域的问题解决方案在传统框架中一般来说有两种方案例如在laravel中直接在入口文件index.php中加上允许跨域代码,或者通过nginx反向代理配置在laravel中header(&#...

Hyperf缓存封装

hyperf官方的缓存文档写得很好,但是对于一个从传统框架比如laravel thinkphp转到这上面来学习的同学就不是很友好了。原理都很好,自动维护缓存,注解缓存这些东西,在我开始学习php的时候...

Hyperf的redis异步队列实战

突发奇想想写一个RTS战略类游戏。RTS战略类游戏核心玩法肯定是有养成啊,比如建筑升级啊,征兵队列啊,之类的,总之就是用户现在点了操作但是拿不到结果,可能要等几十分钟或者更久拿到结果。现在我们来实现以...

Hyperf中间件验证用户登录状态

才开始接触hyperf,就被他惊人的并发处理性能所惊呆了。所以在工作空余之时学习一下hyperf。今天要学习一下hyperf的中间件的使用。新建一个中间件,主要功能就是取每次请求的header头里面的...

Hyperf表单数据验证器

Hyperf表单数据验证器

hyperf虽然基于swoole,但是风格很像laravel,所以上手还是挺快的。记录一下基于hyperf的表单验证器的代码。因为写代码喜欢一把梭,所以太过解耦的验证类就不用了,太麻烦了。简单一点。照...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。