zoukankan      html  css  js  c++  java
  • 全栈微信小程序商城 学习笔记之六 AOP与全局异常处理

    正确理解异常处理流程

    新建Banner模型
    applicationapimodelBanner.php

    class Banner
    {
        public static function getBannerById($id)
        {
          //根据id获取banner信息
          return 'this is banner info';
        }
    }
    

    使用
    applicationapicontrollerv1Banner.php

    use appapimodelBanner as BannerModel;
    class Banner
    {
        public function getBanner($id)
        {
          $validate = new IDMustBePositiveInt();
          $validate->goCheck();
          $banner = BannerModel::getBannerByID($id)
          return $banner;
        }
    }
    

    固有的处理异常的思维模式与流程

    applicationapimodelBanner.php

    class Banner
    {
        public static function getBannerById($id)
        {
          try{
              1 / 0;
          }catch (Exception $ex) {
              throw $ex; //使用tp5全局异常
          }
          return 'this is banner info';
        }
    }
    

    开启调试模式以查看服务器返回的错误详细信息
    applicationconfig.php

    return [
      'app_debug' => true
    ];
    

    此时调用接口将返回

    用json对象的形式返回
    applicationapicontrollerv1Banner.php

    <?php
    
    
    namespace appapicontrollerv1;
    
    use appapimodelBanner as BannerModel;
    use appapivalidateIDMustBePositiveInt;
    use thinkException;
    
    class Banner
    {
        public function getBanner($id)
        {
            (new IDMustBePositiveInt())->goCheck();
            try {
                $banner = BannerModel::getBannerByID($id);
            } catch (Exception $ex) {
                $err = [
                    'error_code' => 10001,
                    'msg ' => $ex->getMessage()
                ];
                //转成json
                //指明状态码
                return json($err, 400);
            }
        }
    }
    

    查看结果

    自定义全局异常处理

    对tp5异常处理类进行重写
    applicationconfig.php

    return [
      'exception_handle'=>'applibexceptionExceptionHandler',
    ];
    

    applicationlibexceptionExceptionHandler.php

    class ExceptionHandler extends Handle
    {
    
    }
    

    统一描述错误
    applicationlibexceptionBaseException.php

    class BaseException extends Exception
    {
        public $code = 400; //状态码
        public $msg = '参数错误'; // 错误信息
        public $errorCode = 10000; //自定义错误码
    }
    

    applicationlibexceptionBannerMissException.php

    class BannerMissException extends BaseException
    {
      public $code = 404;
      public $msg = "请求的Banner不存在";
      public $errorCode = 40000;
    }
    

    applicationlibexceptionExceptionHandler.php

    class ExceptionHandler extends Handle
    {
        public function render(Exception $e)
        {
          return json('~~~~') //先进行一次测试,看看异常是否都会进入
        }
    }
    

    测试,重写成功!

    自定义异常
    applicationlibexceptionExceptionHandler.php

    class ExceptionHandler extends Handle
    {
      private $code;
      private $msg;
      private $errorCode;
      //注意这里使用的是Exception
      public function render(Exception $e){
        if($e instanceof BaseException) { 
          //如果是自定义异常,则控制http状态码,不需要记录日志
          //因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
          //不应当记录日志
          $this->code = $e -> code;
          $this->msg= $e -> msg;
          $this->errorCode= $e -> errorCode;
        } else {
          // 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
          $this->code = 500;
          $this->msg ='服务器内部错误';
          $this->errorCode = 999;
        }
        $request = Request::instance();
        $result = [
          'msg' => $this->msg,
          'error_code ' => $this->errorCode ,
          //返回url
          'request_url' => $request->url(),
        ];
        return json($result, $this->$code);
      }
    }
    

    测试自定义异常
    applicationapimodelBanner.php

    class Banner
    {
        public static function getBannerById($id)
        {
          return null;
        }
    }
    

    applicationapicontrollerv1Banner.php

    class Banner
    {
        public function getBanner($id)
        {
            $validate = new IDMustBePositiveInt();
            $validate->goCheck();
            $banner = BannerModel::getBannerByID($id);
            if (!$banner) {
                throw new BannerMissException();
            }
            return $banner;
        }
    }
    

    日志系统

    记录日志才能发现和解决问题

    public/index.php

    define('LOG_PATH', __DIR__. '/../log/'); //用自定义的路径覆盖tp5默认日志路径,要放在加载框架引导之前
    

    在全局异常处理中加入记录日志

    关闭tp5默认记录日志行为

    applicationconfig.php

    return [
        'log'                    => [
          // 日志记录方式,内置 file socket 支持扩展
          // 关闭自动记录日志,请将type设置为test
          'type'  => 'test',
          // 日志保存目录
          'path'  => LOG_PATH,
          // 日志记录级别
          'level' => ['sql'],
      ],
    ]
    

    加入记录日志

    applicationlibexceptionExceptionHandler.php

    class ExceptionHandler extends Handle
    {
      public function render(Exception $e){
        if($e instanceof BaseException) {
          $this->code = $e -> code;
          $this->msg= $e -> msg;
          $this->errorCode= $e -> errorCode;
        } else {
          $this->code = 500;
          $this->msg ='服务器内部错误';
          $this->errorCode = 999;
          $this->recordErrorLog($e);
        }
        $request = Request::instance();
        $result = [
          'msg' => $this->msg,
          'error_code ' => $this->errorCode ,
          'request_url' => $request->url(),
        ];
        return json($result, $this->$code);
      }
      
      private function recordErrorLog(Exception $e)
      {
        Log::init([
          'type' => 'File', //用文件方式保存日志
          'path' => LOG_PATH, 
          'level' => ['error'] //低于这个级别不会被记录
        ])
        Log::record($e->getMessage(),'error');
      }
    }
    
    

    全局异常处理应用

    加个开关,让前后台都能接收到方便阅读的信息
    applicationlibexceptionExceptionHandler.php (最终代码)

    <?php
    
    namespace applibexception;
    
    use thinkexceptionHandle;
    use thinkLog;
    use thinkRequest;
    use Exception;
    
    class ExceptionHandler extends Handle
    {
        private $code;
        private $msg;
        private $errorCode;
    
        public function render(Exception $e)
         {
            if ($e instanceof BaseException)
            {
                $this->code = $e->code;
                $this->msg = $e->msg;
                $this->errorCode = $e->errorCode;
            }
            else{
                // config是tp5助手函数,用于读取配置信息
                if(config('app_debug')){
                    // 调试状态下需要显示TP默认的异常页面,是供后端人员浏览的信息,错误不会被记录日志
                    return parent::render($e);
                }
                $this->code = 500;
                $this->msg = 'sorry,we make a mistake. (^o^)Y';
                $this->errorCode = 999;
                $this->recordErrorLog($e);
            }
    
            $request = Request::instance();
            $result = [
                'msg'  => $this->msg,
                'error_code' => $this->errorCode,
                'request_url' => $request = $request->url()
            ];
            return json($result, $this->code);
        }
    
        /*
         * 将异常写入日志
         */
        private function recordErrorLog(Exception $e)
        {
            Log::init([
                'type'  =>  'File',
                'path'  =>  LOG_PATH,
                'level' => ['error']
            ]);
            Log::record($e->getMessage(),'error');
        }
    }
    

    参数异常错误

    applicationlibexceptionParameterException.php

    class ParameterException extends BaseException{
      public $code = 400;
      public $msg = '参数错误';
      public $errorCode = 10000;
    }
    

    applicationapivalidateBaseValidate.php

    class BaseValidate extends Validate
    {
        // 检测所有客户端发来的参数是否符合验证类规则
        public function goCheck()
        {
            $request = Request::instance();
            $params = $request->param();
            $result = $this->check($params);
            if (!$result) { 
              $e = new ParameterException()
              $e->msg = $this->error;
              throw $e
            } else {
                return true;
            }
        }
    }
    

    全局异常处理应用

    使用构造函数
    applicationapivalidateBaseValidate.php(最终代码)

    <?php
    
    
    namespace appapivalidate;
    
    
    use applibexceptionParameterException;
    use thinkRequest;
    use thinkValidate;
    
    class BaseValidate extends Validate
    {
        // 检测所有客户端发来的参数是否符合验证类规则
        public function goCheck()
        {
            $request = Request::instance();
            $params = $request->param();
            //同时校验多个规则
            $result = $this->batch()->check($params);
            if (!$result) {
                $e = new ParameterException([
                    'msg' => $this->error,
                    'code' => 400,
                    'errorCode' => 10002
                ]);
              throw $e;
            } else {
                return true;
            }
        }
    }
    

    构造函数形式要先对BaseException做如下更改
    applicationlibexceptionBaseException.php (最终代码)

    <?php
    namespace applibexception;
    use thinkException;
    
    class BaseException extends Exception
    {
        public $code = 400;
        public $msg = 'invalid parameters';
        public $errorCode = 999;
    
        /**
         * 构造函数,接收一个关联数组
         * @param array $params 关联数组只应包含code、msg和errorCode,且不应该是空值
         */
        public function __construct($params=[])
        {
            if(!is_array($params)){
                return;
            }
            if(array_key_exists('code',$params)){
                $this->code = $params['code'];
            }
            if(array_key_exists('msg',$params)){
                $this->msg = $params['msg'];
            }
            if(array_key_exists('errorCode',$params)){
                $this->errorCode = $params['errorCode'];
            }
        }
    }
    
  • 相关阅读:
    Java中ArrayList与LinkedList的区别
    Java中String、StringBuffer、StringBuilder的区别
    Java中的String类能否被继承?为什么?
    JAVA有哪些数据类型?基本数据类型各占多少个字节
    Linux远程复制命令SCP
    CentOS添加用户并加入sudo权限
    nginx配置反向代理解决前后端分离跨域问题
    执行ssh-add时出现Could not open a connection to your authentication agent
    Git 修改源地址
    ssh配置git clone简易流程
  • 原文地址:https://www.cnblogs.com/Qyhg/p/14059232.html
Copyright © 2011-2022 走看看