yii2 开发api接口时优雅的处理全局异常的方法


Posted in PHP onMay 14, 2019

前言:个人觉得,学习或温习一套Web框架,在快速阅读一遍文档后,应从路由,控制器,请求/响应对象,数据模型(Logic,Dao,Entity),全局异常处理几个方面下手,这几项了解后,框架上手就游刃有余了。然后我比较喜欢在开工前整理好框架的全局异常处理,方便写 api时错误的统一响应。

api接口的开发过程中,我们需要对用户数据进行严格的校验,防止非法输入对服务产生安全问题,在开发过程中,我比较喜欢即时的以抛出异常的方式中断请求的处理,并以全局异常处理器格式化处理后统一返回给客户端。

今天就把 yii2 自带的全局异常处理器改写至对 api 友好(yii2yii\web\HttpException默认对 web 请求友好,都是以text/html的方式返回错误描述,对api不友好,api当然是json)。

注册异常处理器

yii2也是以 controller/action 的方式定义一个异常处理器的,我们可以在 components=>errorHandler中自定义。

# config/web.php
'components' => [
  'errorHandler' => [
    'errorAction' => 'exception/handler'
  ]
]

异常处理器

定义相应的异常处理器,app\actions\ErrorApiAction 继承 yii\web\ErrorAction,可以拿到yii2为我们整理好的全局异常。

# controllers/ExceptionController.php
<?php

namespace app\controllers;

use yii\web\Controller;

class ExceptionController extends Controller
{
  /**
   * 为 actionHandler 挂载独立的 action
   * @return array
   */
  public function actions()
  {
    return [
      'handler' => [
        'class' => 'app\actions\ErrorApiAction',
      ]
    ];
  }
}

api友好的错误异常处理器,这里我也只是简单的把响应格式改了一下,异常的上下文还是用yii2自带的处理的。

#actions/ErrorApiAction.php
<?php
/**
 * @author wangzhijian@styd.com
 * @date 2019-5-13 17:20:10
 * Api 全局错误异常处理器
 */

namespace app\actions;

use Yii;
use yii\web\ErrorAction;
use yii\web\Response;

class ErrorApiAction extends ErrorAction
{
  public function run()
  {
    // 根据异常类型设定相应的响应码
    Yii::$app->getResponse()->setStatusCodeByException($this->exception);
    // json 格式返回
    Yii::$app->getResponse()->format = Response::FORMAT_JSON;
    // 返回的内容数据
    return [
      'msg' => $this->exception->getMessage(),
      'err' => $this->exception->getCode()
    ];
  }
}

异常实体

主要是简单的把状态码的传递封装一下,用更容易理解的类名来代理传递。
exceptions/HttpException.php

<?php
/**
 * app 异常基础类
 */

namespace app\exceptions;

class HttpException extends \yii\web\HttpException
{
  public function __construct($message = null, $code = 0, \Exception $previous = null)
  {
    parent::__construct($this->statusCode, $message, $code, $previous);
  }
}

exceptions/HttpForbiddenException.php

<?php
/**
 * 400 bad request
 */

namespace app\exceptions;

class HttpBadRequestException extends HttpException
{
  public $statusCode = 400;
}

exceptions/HttpUnauthorizedException.php

<?php
/**
 * 401 unauthorized
 */

namespace app\exceptions;

class HttpUnauthorizedException extends HttpException
{
  public $statusCode = 401;
}

exceptions/HttpForbiddenException.php

<?php
/**
 * 403 forbidden
 */

namespace app\exceptions;

class HttpForbiddenException extends HttpException
{
  public $statusCode = 403;
}

exceptions/HttpNotFoundException.php

<?php
/**
 * 404 not found
 */

namespace app\exceptions;

class HttpNotFoundException extends HttpException
{
  public $statusCode = 404;
}

使用范例

在一些 service logic model 中根据需要即时抛出异常即可,上层控制器拿到的永远都是正常的返回数据,绝对的2xx响应簇

throw new HttpBadRequestException("具体的非法描述", 4001);
throw new HttpUnauthorizedException("请认证后访问");
throw new HttpForbiddenException("无权访问");
throw new HttpNotFoundException("请求资源不存在");

yii2 开发api接口时优雅的处理全局异常的方法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php合并数组array_merge函数运算符加号与的区别
Oct 31 PHP
dedecms 批量提取第一张图片最为缩略图的代码(文章+软件)
Oct 29 PHP
GBK的页面输出JSON格式的php函数
Feb 16 PHP
PHP中usort在值相同时改变原始位置问题的解决方法
Nov 27 PHP
php 发送带附件邮件示例
Jan 23 PHP
最新制作ThinkPHP3.2.3完全开发手册
Nov 23 PHP
php反射类ReflectionClass用法分析
May 12 PHP
CodeIgniter记录错误日志的方法全面总结
May 17 PHP
Yii2 rbac权限控制之rule教程详解
Jun 23 PHP
PHP数组编码gbk与utf8互相转换的两种方法
Sep 01 PHP
centos下file_put_contents()无法写入文件的原因及解决方法
Apr 01 PHP
thinkPHP事务操作简单案例分析
Oct 17 PHP
yii2的restful api路由实例详解
May 14 #PHP
php的扩展写法总结
May 14 #PHP
PHP利用pdo_odbc实现连接数据库示例【基于ThinkPHP5.1搭建的项目】
May 13 #PHP
thinkPHP框架通过Redis实现增删改查操作的方法详解
May 13 #PHP
ThinkPHP3.2框架自带分页功能实现方法示例
May 13 #PHP
PHP使用Redis实现Session共享的实现示例
May 12 #PHP
如何让PHP编码更加好看利于阅读
May 12 #PHP
You might like
PHP分页效率终结版(推荐)
2013/07/01 PHP
详解Laravel5.6 Passport实现Api接口认证
2018/07/27 PHP
百度留言本js 大家可以参考下
2009/10/13 Javascript
extJs 文本框后面加上说明文字+下拉列表选中值后触发事件
2009/11/27 Javascript
js页面跳转的常用方法整理
2013/10/18 Javascript
js获取select标签的值且兼容IE与firefox
2013/12/30 Javascript
jquery中$(#form :input)与$(#form input)的区别
2014/08/18 Javascript
jquery表单验证需要做些什么
2015/11/17 Javascript
jQuery获取及设置表单input各种类型值的方法小结
2016/05/24 Javascript
微信小程序版翻牌小游戏
2018/01/26 Javascript
vue.js使用v-pre与v-html输出HTML操作示例
2018/07/07 Javascript
Layui 设置select下拉框自动选中某项的方法
2018/08/14 Javascript
JQuery扩展对象方法操作示例
2018/08/21 jQuery
JavaScript&quot;模拟事件&quot;的注意要点详解
2019/02/13 Javascript
如何在vue 中使用柱状图 并自修改配置
2021/01/21 Vue.js
Python语言的12个基础知识点小结
2014/07/10 Python
python写入中英文字符串到文件的方法
2015/05/06 Python
Python出现segfault错误解决方法
2016/04/16 Python
python中urlparse模块介绍与使用示例
2017/11/19 Python
目前最全的python的就业方向
2018/06/05 Python
浅谈Series和DataFrame中的sort_index方法
2018/06/07 Python
Python闭包思想与用法浅析
2018/12/27 Python
解决python中画图时x,y轴名称出现中文乱码的问题
2019/01/29 Python
python添加菜单图文讲解
2019/06/04 Python
Django结合ajax进行页面实时更新的例子
2019/08/12 Python
Python函数式编程指南:对生成器全面讲解
2019/11/19 Python
Pycharm 2020年最新激活码(亲测有效)
2020/09/18 Python
python使用Thread的setDaemon启动后台线程教程
2020/04/25 Python
用python制作个视频下载器
2021/02/01 Python
植村秀加拿大官网:Shu Uemura加拿大
2019/09/03 全球购物
Weblogic的布署方式
2013/08/23 面试题
南京某公司笔试题
2013/01/27 面试题
计算机学生求职信范文
2014/01/30 职场文书
2014年劳动部工作总结
2014/12/11 职场文书
楚门的世界观后感
2015/06/03 职场文书
环保证明
2015/06/23 职场文书