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加MYSQL服务器
Oct 09 PHP
PHP 中的面向对象编程:通向大型 PHP 工程的办法
Dec 03 PHP
一段防盗连的PHP代码
Dec 06 PHP
php 无限分类的树类代码
Dec 03 PHP
基于PHP常用字符串的总结(待续)
Jun 07 PHP
php设计模式之命令模式使用示例
Mar 02 PHP
php中HTTP_REFERER函数用法实例
Nov 21 PHP
WordPress中获取所使用的模板的页面ID的简单方法
Dec 31 PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
Apr 09 PHP
php+lottery.js实现九宫格抽奖功能
Jul 21 PHP
php use和include区别总结
Oct 13 PHP
laravel通过a标签从视图向控制器实现传值
Oct 15 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递归方法实现无限分类实例代码
2014/02/28 PHP
PHP数据库操作之基于Mysqli的数据库操作类库
2014/04/19 PHP
php向js函数传参的几种方法
2014/08/10 PHP
PHP中exec函数和shell_exec函数的区别
2014/08/20 PHP
详解PHP神奇又有用的Trait
2019/03/25 PHP
Js从头学起(基本数据类型和引用类型的参数传递详细分析)
2012/02/16 Javascript
《JavaScript高级程序设计》阅读笔记(二) ECMAScript中的原始类型
2012/02/27 Javascript
解析js原生方法创建表格效率测试
2013/07/08 Javascript
jQuery将所有被选中的checkbox某个属性值连接成字符串的方法
2015/01/24 Javascript
JavaScript设计模式之工厂模式和构造器模式
2015/02/11 Javascript
解决jquery实现的radio重新选中的问题
2015/07/03 Javascript
jQuery实现的漂亮表单效果代码
2015/08/18 Javascript
AngularJS 实现JavaScript 动画效果详解
2016/09/08 Javascript
JS中的两种数据类型及实现引用类型的深拷贝的方法
2018/08/12 Javascript
Node.js assert断言原理与用法分析
2019/01/04 Javascript
Vue监听页面刷新和关闭功能
2019/06/20 Javascript
十分钟教你上手ES2020新特性
2020/02/12 Javascript
vue 路由守卫(导航守卫)及其具体使用
2020/02/25 Javascript
[04:47]DOTA2-潍坊风行电子俱乐部探秘
2014/08/08 DOTA
Python中的魔法方法深入理解
2014/07/09 Python
Python输出汉字字库及将文字转换为图片的方法
2016/06/04 Python
Python正则表达式教程之二:捕获篇
2017/03/02 Python
使用Python横向合并excel文件的实例
2018/12/11 Python
详解Python+Selenium+ChromeDriver的配置和问题解决
2021/01/19 Python
html5构建触屏网站之touch事件介绍
2013/01/07 HTML / CSS
美国东北部户外服装和设备零售商:Eastern Mountain Sports
2016/10/05 全球购物
美国电子产品折扣网站:Daily Steals
2017/05/20 全球购物
建筑设计师岗位职责
2013/11/18 职场文书
幼儿园新学期寄语
2014/01/18 职场文书
数控技术专业毕业自荐书范文
2014/02/05 职场文书
任命书范本大全
2014/06/06 职场文书
预备党员对照检查材料思想汇报
2014/09/24 职场文书
财务经理岗位职责
2015/01/31 职场文书
大学生党课心得体会
2016/01/07 职场文书
spring cloud gateway中如何读取请求参数
2021/07/15 Java/Android
Windows Server 2012 R2服务器安装与配置的完整步骤
2022/07/15 Servers