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 相关文章推荐
基于curl数据采集之正则处理函数get_matches的使用
Apr 28 PHP
PHP字符串的连接的简单实例
Dec 30 PHP
PHP动态生成javascript文件的2个例子
Apr 11 PHP
php中把美国时间转为北京时间的自定义函数分享
Jul 28 PHP
thinkphp循环结构用法实例
Nov 24 PHP
CodeIgniter与PHP5.6的兼容问题
Jul 16 PHP
PHP如何通过传引用的思想实现无限分类(代码简单)
Oct 13 PHP
php实现scws中文分词搜索的方法
Dec 25 PHP
PHP两种实现无级递归分类的方法
Mar 02 PHP
laravel withCount 统计关联数量的方法
Oct 10 PHP
解决laravel(5.5)访问public报错的问题
Oct 12 PHP
PHP简单实现图片格式转换(jpg转png,gif转png等)
Oct 30 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 Memcached应用实现代码
2010/02/08 PHP
PHP 魔术变量和魔术函数详解
2015/02/25 PHP
PHP闭包函数详解
2016/02/13 PHP
PHP面向对象程序设计高级特性详解(接口,继承,抽象类,析构,克隆等)
2016/12/02 PHP
PHP检测接口Traversable用法详解
2017/12/29 PHP
thinkphp3.2框架中where条件查询用法总结
2019/08/13 PHP
ASP.NET jQuery 实例11 通过使用jQuery validation插件简单实现用户登录页面验证功能
2012/02/03 Javascript
jQuery层次选择器用法示例
2016/09/09 Javascript
Jquery EasyUI Datagrid右键菜单实现方法
2016/12/30 Javascript
Mac下使用charles遇到的问题以及解决办法
2017/01/10 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
详解VUE的状态控制与延时加载刷新
2017/03/27 Javascript
详解IWinter 一个路由转控制器的 Nodejs 库
2017/11/15 NodeJs
JavaScript检查数据中是否存在相同的元素(两种方法)
2018/10/07 Javascript
微信小程序 动态修改页面数据及参数传递过程详解
2019/09/27 Javascript
JS实现简单的表格增删
2020/01/16 Javascript
webpack的 rquire.context用法实现工程自动化的方法
2020/02/07 Javascript
web.py在SAE中的Session问题解决方法(使用mysql存储)
2015/06/24 Python
详解python里使用正则表达式的全匹配功能
2017/10/19 Python
浅谈python 里面的单下划线与双下划线的区别
2017/12/01 Python
Python遍历numpy数组的实例
2018/04/04 Python
详谈python3中用for循环删除列表中元素的坑
2018/04/19 Python
Sanic框架基于类的视图用法示例
2018/07/18 Python
python实现决策树分类
2018/08/30 Python
python和pywin32实现窗口查找、遍历和点击的示例代码
2020/04/01 Python
python实现图片素描效果
2020/09/26 Python
宝拉珍选官方旗舰店:2%水杨酸精华液,收缩毛孔粗大和祛痘
2018/07/01 全球购物
PHP面试题集
2016/12/18 面试题
幼儿师范毕业生自荐信
2013/11/09 职场文书
开办加工厂创业计划书
2014/01/03 职场文书
有创意的广告词
2014/03/18 职场文书
企业贷款委托书格式
2014/09/12 职场文书
大学生求职自荐信范文
2015/03/04 职场文书
运动会宣传稿100字
2015/07/23 职场文书
面试提问mysql一张表到底能存多少数据
2022/03/13 MySQL
Win11怎么添加用户?Win11添加用户账户的方法
2022/07/15 数码科技