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&amp;java(一)
Oct 09 PHP
php中获取指定IP的物理地址的代码(正则表达式)
Jun 23 PHP
PHP中实现中文字符进制转换原理分析
Dec 06 PHP
php增删改查示例自己写的demo
Sep 04 PHP
php操作mysqli(示例代码)
Oct 28 PHP
php 发送带附件邮件示例
Jan 23 PHP
php版淘宝网查询商品接口代码示例
Jun 17 PHP
php+mysql删除指定编号员工信息的方法
Jan 14 PHP
CI(Codeigniter)的Setting增强配置类实例
Jan 06 PHP
PHP基于SimpleXML生成和解析xml的方法示例
Jul 17 PHP
laravel-admin 管理平台获取当前登陆用户信息的例子
Oct 08 PHP
WordPress多语言翻译插件 - WPML使用教程
Apr 01 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
一个捕获函数输出的函数
2007/02/14 PHP
PHP新手入门学习方法
2011/05/08 PHP
实例介绍PHP中zip_open()函数用法
2019/02/15 PHP
PHP面向对象程序设计内置标准类,普通数据类型转为对象类型示例
2019/06/12 PHP
jquery选择器之属性过滤选择器详解
2014/01/27 Javascript
Jquery插件编写简明教程
2014/03/25 Javascript
JS获得图片alt信息的方法
2015/04/01 Javascript
Angular外部使用js调用Angular控制器中的函数方法或变量用法示例
2016/08/05 Javascript
ES6中class类用法实例浅析
2017/04/06 Javascript
webpack进阶——缓存与独立打包的用法
2017/08/02 Javascript
react 实现页面代码分割、按需加载的方法
2018/04/03 Javascript
VUE-cli3使用 svg-sprite-loader
2018/10/20 Javascript
傻瓜式vuex语法糖kiss-vuex整理
2018/12/21 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
vue-quill-editor 自定义工具栏和自定义图片上传路径操作
2020/08/03 Javascript
微信小程序实现日历签到
2020/09/21 Javascript
[02:34]2016完美“圣”典风云人物:BurNIng专访
2016/12/10 DOTA
Python捕捉和模拟鼠标事件的方法
2015/06/03 Python
EM算法的python实现的方法步骤
2018/01/02 Python
python中利用h5py模块读取h5文件中的主键方法
2018/06/05 Python
python中的tcp示例详解
2018/12/09 Python
解决python中画图时x,y轴名称出现中文乱码的问题
2019/01/29 Python
python 多线程对post请求服务器测试并发的方法
2019/06/13 Python
pyqt5 实现 下拉菜单 + 打开文件的示例代码
2019/06/20 Python
pytorch自定义初始化权重的方法
2019/08/17 Python
基于python的itchat库实现微信聊天机器人(推荐)
2019/10/29 Python
opencv设置采集视频分辨率方式
2019/12/10 Python
Tensorflow读取并输出已保存模型的权重数值方式
2020/01/04 Python
Pytorch中的自动求梯度机制和Variable类实例
2020/02/29 Python
python实现Oracle查询分组的方法示例
2020/04/30 Python
html5唤起app的方法
2017/11/30 HTML / CSS
非功能性需求都包括哪些方面
2013/10/29 面试题
幼儿园中班下学期评语
2014/04/18 职场文书
社区安全生产月活动总结
2014/07/05 职场文书
审计局2014法制宣传日活动总结
2014/11/01 职场文书
2016年七夕爱情寄语
2015/12/04 职场文书