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在字符断点处截断文字的实现代码
Apr 21 PHP
php小技巧 把数组的键和值交换形成了新的数组,查找值取得键
Jun 02 PHP
php学习笔记 [预定义数组(超全局数组)]
Jun 09 PHP
php数组函数序列之array_combine() - 数组合并函数使用说明
Oct 29 PHP
控制PHP的输出:缓存并压缩动态页面
Jun 11 PHP
php中函数前加&amp;符号的作用分解
Jul 08 PHP
php判断访问IP的方法
Jun 19 PHP
详解PHP中的状态模式编程
Aug 11 PHP
yii去掉必填项中星号的方法
Dec 28 PHP
WordPress中获取所使用的模板的页面ID的简单方法
Dec 31 PHP
详解PHP实现定时任务的五种方法
Jul 25 PHP
安装PHP扩展时解压官方 tgz 文件后没有configure文件无法进行配置编译的问题
Aug 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
php session处理的定制
2009/03/16 PHP
php中实现简单的ACL 完结篇
2011/09/07 PHP
php输出xml格式字符串(用的这个)
2012/07/12 PHP
让textarea控件的滚动条怎是位与最下方
2007/04/20 Javascript
JavaScript聚焦于第一个字段的代码
2010/10/15 Javascript
简易js代码实现计算器操作
2013/04/15 Javascript
javascript实现TreeView 无刷新展开的实例代码
2013/07/13 Javascript
浅谈JS原型对象和原型链
2016/03/02 Javascript
JS实现类似百叶窗下拉菜单效果
2016/12/30 Javascript
vue.js中mint-ui框架的使用方法
2017/05/12 Javascript
express+mockjs实现模拟后台数据发送功能
2018/01/07 Javascript
详解使用create-react-app快速构建React开发环境
2018/05/16 Javascript
vue-cli整合vuex的时候,修改actions和mutations,实现热部署的方法
2018/09/19 Javascript
vue实现的双向数据绑定操作示例
2018/12/04 Javascript
详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)
2019/04/09 Javascript
防止Layui form表单重复提交的实现方法
2019/09/10 Javascript
Vue3.0中的monorepo管理模式的实现
2019/10/14 Javascript
Python检测QQ在线状态的方法
2015/05/09 Python
Python将多个excel表格合并为一个表格
2021/02/22 Python
使用python采集脚本之家电子书资源并自动下载到本地的实例脚本
2018/10/23 Python
Pycharm无法显示动态图片的解决方法
2018/10/28 Python
python中logging模块的一些简单用法的使用
2019/02/22 Python
python读写csv文件方法详细总结
2019/07/05 Python
python list等分并从等分的子集中随机选取一个数
2020/11/16 Python
需要知道的CSS3动画技术
2010/01/01 HTML / CSS
人力资源主管岗位职责
2014/01/29 职场文书
幼儿园教师教育感言
2014/02/28 职场文书
自我鉴定标准格式
2014/03/19 职场文书
企业指导教师评语
2014/04/28 职场文书
投资建议书模板
2014/05/12 职场文书
组工干部对照检查材料
2014/08/25 职场文书
甘南现象心得体会
2014/09/11 职场文书
机关干部四风问题自查报告及整改措施
2014/10/26 职场文书
小学教师年度个人总结
2015/02/05 职场文书
干货:如何写好观后感 !
2019/05/21 职场文书
windows10声卡驱动怎么安装?win10声卡驱动安装操作步骤教程
2022/08/05 数码科技