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仿discuz分页效果代码
Oct 02 PHP
php !function_exists(&quot;T7FC56270E7A70FA81A5935B72EACBE29&quot;))代码解密
Jan 07 PHP
PHP类的静态(static)方法和静态(static)变量使用介绍
Feb 19 PHP
PHP 将逗号、空格、回车分隔的字符串转换为数组的函数
Jun 07 PHP
深入理解PHP之数组(遍历顺序)  Laruence原创
Jun 13 PHP
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
Apr 25 PHP
php中serialize序列化与json性能测试的示例分析
Apr 27 PHP
PHP实现类似于C语言的文件读取及解析功能
Sep 01 PHP
PHP调用API接口实现天气查询功能的示例
Sep 21 PHP
PHP网页安全认证的实例详解
Sep 28 PHP
解决PHP使用CURL发送GET请求时传递参数的问题
Oct 11 PHP
php生成短网址/短链接原理和用法实例分析
May 29 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自动注册登录验证机制实现代码
2011/12/20 PHP
Using the TextRange Object
2006/10/14 Javascript
jquery中的事件处理详细介绍
2013/06/24 Javascript
jQuery function的正确书写方法
2013/08/02 Javascript
读取input:file的路径并显示本地图片的方法
2013/09/23 Javascript
js中匿名函数的创建与调用方法分析
2014/12/19 Javascript
jquery mobile开发常见问题分析
2016/01/21 Javascript
JavaScript数组的一些奇葩行为
2016/01/25 Javascript
xcode中获取js文件的路径方法(推荐)
2016/11/05 Javascript
jQuery实现遍历复选框的方法示例
2017/03/06 Javascript
HTML5+Canvas调用手机拍照功能实现图片上传(下)
2017/04/21 Javascript
vue的Virtual Dom实现snabbdom解密
2017/05/03 Javascript
Nodejs中Express 常用中间件 body-parser 实现解析
2017/05/22 NodeJs
使用JS模拟锚点跳转的实例
2018/02/01 Javascript
Vue实现简单的跑马灯
2020/05/25 Javascript
Vuejs通过拖动改变元素宽度实现自适应
2020/09/02 Javascript
vue中选中多个选项并且改变选中的样式的实例代码
2020/09/16 Javascript
使用python Django做网页
2013/11/04 Python
python二分法实现实例
2013/11/21 Python
python中enumerate函数遍历元素用法分析
2016/03/11 Python
Python列表删除的三种方法代码分享
2017/10/31 Python
python+django加载静态网页模板解析
2017/12/12 Python
详解Python使用Plotly绘图工具,绘制甘特图
2019/04/02 Python
PyQt5 QTable插入图片并动态更新的实例
2019/06/18 Python
python 命名规范知识点汇总
2020/02/14 Python
解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题
2020/07/13 Python
python 如何使用find和find_all爬虫、找文本的实现
2020/10/16 Python
Python操作PostgreSql数据库的方法(基本的增删改查)
2020/12/29 Python
python中openpyxl和xlsxwriter对Excel的操作方法
2021/03/01 Python
ALLSAINTS英国官网:伦敦新锐潮流品牌
2016/09/19 全球购物
银行营业厅大堂经理岗位职责
2014/01/06 职场文书
党员实事承诺书
2014/03/26 职场文书
白血病募捐倡议书
2014/05/14 职场文书
2014年保险业务员工作总结
2014/12/23 职场文书
地方课程教学计划
2015/01/19 职场文书
新农村建设指导员工作总结
2015/08/13 职场文书