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
Dec 14 PHP
PHPUnit PHP测试框架安装方法
Mar 23 PHP
php中常用字符串处理代码片段整理
Nov 07 PHP
网页上facebook分享功能具体实现
Jan 26 PHP
php格式输出文件var_export函数实例
Nov 15 PHP
php异常处理方法实例汇总
Jun 24 PHP
PHP基于phpqrcode生成带LOGO图像的二维码实例
Jul 10 PHP
php项目中百度 UEditor 简单安装调试和调用
Jul 15 PHP
thinkphp3.2点击刷新生成验证码
Feb 16 PHP
mysql_escape_string()函数用法分析
Apr 25 PHP
thinkPHP5.0框架API优化后的友好性分析
Mar 17 PHP
PHP CodeIgniter分页实例及多条件查询解决方案(推荐)
May 20 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
PHPMYADMIN 简明安装教程 推荐
2010/03/07 PHP
PHP开发工具ZendStudio下Xdebug工具使用说明详解
2013/11/11 PHP
PHP使用PDO创建MySQL数据库、表及插入多条数据操作示例
2019/05/30 PHP
js no-repeat写法 背景不重复
2009/03/18 Javascript
JS随机生成不重复数据的实例方法
2013/07/17 Javascript
js函数调用的方式
2014/05/06 Javascript
js+jquery实现图片裁剪功能
2015/01/02 Javascript
情人节单身的我是如何在敲完代码之后收到12束玫瑰的(javascript)
2015/08/21 Javascript
AngularJS基础 ng-srcset 指令简单示例
2016/08/03 Javascript
AngularJs Modules详解及示例代码
2016/09/01 Javascript
js中new一个对象的过程
2017/02/20 Javascript
JS排序之冒泡排序详解
2017/04/08 Javascript
js每隔两秒输出数组中的一项(实例)
2017/05/28 Javascript
基于Vue2.0+ElementUI实现表格翻页功能
2017/10/23 Javascript
详细分析jsonp的原理和实现方式
2017/11/20 Javascript
解决在vue项目中,发版之后,背景图片报错,路径不对的问题
2018/03/06 Javascript
Vue绑定内联样式问题
2018/10/17 Javascript
javascript面向对象三大特征之继承实例详解
2019/07/24 Javascript
JavaScript代码压缩工具UglifyJS和Google Closure Compiler的基本用法
2020/04/13 Javascript
[15:58]DOTA2国际邀请赛采访专栏:Tongfu.Sansheng&KingJ,DK.rOtk
2013/08/08 DOTA
Python MySQLdb Linux下安装笔记
2015/05/09 Python
Python编程之多态用法实例详解
2015/05/19 Python
浅析Python中的赋值和深浅拷贝
2017/08/15 Python
python中的不可变数据类型与可变数据类型详解
2018/09/16 Python
在python 中实现运行多条shell命令
2019/01/07 Python
用scikit-learn和pandas学习线性回归的方法
2019/06/21 Python
Python3实现二叉树的最大深度
2019/09/30 Python
python opencv实现简易画图板
2020/08/27 Python
纯CSS实现预加载动画效果
2017/09/06 HTML / CSS
G-Form护具官方网站:美国运动保护装备
2019/09/04 全球购物
化工专业个人的求职信范文
2013/11/28 职场文书
十岁生日同学答谢词
2014/01/19 职场文书
开业庆典活动策划方案
2014/09/21 职场文书
2015建军节87周年演讲稿
2015/03/19 职场文书
2016年班主任培训心得体会
2016/01/07 职场文书
go语言中http超时引发的事故解决
2021/06/02 Golang