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一些服务器端特性的配置加强php的安全
Oct 09 PHP
简单的过滤字符串中的HTML标记
Dec 25 PHP
php设计模式 Bridge (桥接模式)
Jun 26 PHP
php中将时间差转换为字符串提示的实现代码
Aug 08 PHP
php中将网址转换为超链接的函数
Sep 02 PHP
PHP中开启gzip压缩的2种方法
Jan 31 PHP
php输出全球各个时区列表的方法
Mar 31 PHP
PHP SPL标准库之数据结构栈(SplStack)介绍
May 12 PHP
php使用CURL不依赖COOKIEJAR获取COOKIE的方法
Jun 17 PHP
php使用Session和文件统计在线人数
Jul 04 PHP
PHP操作mysql数据库分表的方法
Jun 09 PHP
php自动加载代码实例详解
Feb 26 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
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
Windows Apache2.2.11及Php5.2.9-1的安装与配置方法
2009/06/08 PHP
php另类上传图片的方法(PHP用Socket上传图片)
2013/10/30 PHP
php用户密码加密算法分析【Discuz加密算法】
2016/10/12 PHP
laravel 5.5 关闭token的3种实现方式
2019/10/24 PHP
Javascript中的isNaN函数使用说明
2011/11/10 Javascript
在javascript中实现函数数组的方法
2013/12/25 Javascript
使用JavaScript制作一个简单的计数器的方法
2015/07/07 Javascript
ajax如何实现页面局部跳转与结果返回
2015/08/24 Javascript
RequireJS入门一之实现第一个例子
2015/09/30 Javascript
js实现精确到秒的日期选择器完整实例
2016/04/30 Javascript
javascript 判断页面访问方式电脑或者移动端
2016/09/19 Javascript
从零开始最小实现react服务器渲染详解
2018/01/26 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
Vue 实现从小到大的横向滑动效果详解
2019/10/16 Javascript
vue 实现动态路由的方法
2020/07/06 Javascript
解决vue+webpack项目接口跨域出现的问题
2020/08/10 Javascript
openLayer4实现动态改变标注图标
2020/08/17 Javascript
Javascript节流函数throttle和防抖函数debounce
2020/12/03 Javascript
从零学python系列之新版本导入httplib模块报ImportError解决方案
2014/05/23 Python
python实现自动发送邮件
2018/06/20 Python
python实现反转部分单向链表
2018/09/27 Python
python实现银联支付和支付宝支付接入
2019/05/07 Python
如何在VSCode上轻松舒适的配置Python的方法步骤
2019/10/28 Python
浅谈python量化 双均线策略(金叉死叉)
2020/06/03 Python
pytorch实现查看当前学习率
2020/06/24 Python
python多线程和多进程关系详解
2020/12/14 Python
英国航空官网:British Airways
2016/09/11 全球购物
Maison Lab荷兰:名牌Outlet购物
2018/08/10 全球购物
美国价格实惠的在线眼镜网站:Zeelool
2020/12/25 全球购物
成教自我鉴定
2013/10/27 职场文书
机械工程师的岗位职责
2013/11/17 职场文书
警察思想汇报
2014/01/04 职场文书
幼儿园欢迎词范文
2015/01/26 职场文书
安全教育培训制度
2015/08/06 职场文书
SpringBoot生成License的实现示例
2021/06/16 Java/Android