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 相关文章推荐
初学者入门:细述PHP4的核心Zend
Sep 05 PHP
服务器端解压缩zip的脚本
Dec 22 PHP
linux下 C语言对 php 扩展
Dec 14 PHP
php 论坛采集程序 模拟登陆,抓取页面 实现代码
Jul 09 PHP
phpphp图片采集后按原路径保存图片示例
Feb 18 PHP
ThinkPHP调试模式与日志记录概述
Aug 22 PHP
php实现比较全的数据库操作类
Jun 18 PHP
CI配置多数据库访问的方法
Mar 28 PHP
php注册审核重点解析(数据访问)
May 23 PHP
thinkphp 抓取网站的内容并且保存到本地的实例详解
Aug 25 PHP
实例解析php的数据类型
Oct 24 PHP
Laravel实现ORM带条件搜索分页
Oct 24 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函数和特点
2013/08/08 PHP
PHP使用strtotime获取上个月、下个月、本月的日期
2015/12/30 PHP
实例讲解如何在PHP的Yii框架中进行错误和异常处理
2016/03/17 PHP
关于JQuery($.load)事件的用法和分析
2013/04/09 Javascript
防止xss和sql注入:JS特殊字符过滤正则
2013/04/18 Javascript
Angularjs制作简单的路由功能demo
2015/04/14 Javascript
JS填写银行卡号每隔4位数字加一个空格
2016/12/19 Javascript
详解原生js实现offset方法
2017/06/15 Javascript
基于jstree使用AJAX请求获取数据形成树
2017/08/29 Javascript
原生js封装运动框架的示例讲解
2017/10/01 Javascript
解决linux下node.js全局模块找不到的问题
2018/05/15 Javascript
jQuery滑动效果实现方法分析
2018/09/05 jQuery
使用vue2实现带地区编号和名称的省市县三级联动效果
2018/11/05 Javascript
微信小程序防止多次点击跳转(函数节流)
2019/09/19 Javascript
Vue清除定时器setInterval优化方案分享
2020/07/21 Javascript
Python采用socket模拟TCP通讯的实现方法
2014/11/19 Python
10款最好的Web开发的 Python 框架
2015/03/18 Python
Python实现一个Git日志统计分析的小工具
2017/12/14 Python
在Windows中设置Python环境变量的实例讲解
2018/04/28 Python
Python实现全排列的打印
2018/08/18 Python
django表单的Widgets使用详解
2019/07/22 Python
python利用百度云接口实现车牌识别的示例
2020/02/21 Python
python实现爱奇艺登陆密码RSA加密的方法示例详解
2020/05/27 Python
Django-imagekit的使用详解
2020/07/06 Python
HTML5计时器小例子
2013/10/15 HTML / CSS
前端H5 Video常见使用场景简介
2020/08/21 HTML / CSS
美国眼镜在线零售商:Dualens
2019/12/07 全球购物
LUISAVIAROMA德国官网:时尚奢侈品牌购物网站
2020/11/12 全球购物
婚礼新郎父母答谢词
2014/01/16 职场文书
党员干部2014全国两会学习心得体会
2014/03/10 职场文书
道路交通安全实施方案
2014/03/12 职场文书
护士实习自荐信
2015/03/06 职场文书
七年级数学教学反思
2016/02/17 职场文书
画错魏国疆域啦!《派对咖孔明》动画因作画失误于官网致歉
2022/04/07 日漫
MySQL三种方式实现递归查询
2022/04/18 MySQL
Mysql查询时间区间日期列表,不会由于数据表数据影响
2022/04/19 MySQL