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初学者最感迷茫的问题小结
Mar 27 PHP
php下连接ftp实现文件的上传、下载、删除文件实例代码
Jun 03 PHP
php中static静态变量的使用方法详解
Jun 04 PHP
在PHP中养成7个面向对象的好习惯
Jul 17 PHP
Sorting Array Values in PHP(数组排序)
Sep 15 PHP
Function eregi is deprecated (解决方法)
Jun 21 PHP
解析strtr函数的效率问题
Jun 26 PHP
微信营销平台系统?刮刮乐的开发
Jun 10 PHP
php中eval函数的危害与正确禁用方法
Jun 30 PHP
php时间戳格式化显示友好的时间函数分享
Oct 21 PHP
php文件操作小结(删除指定文件/获取文件夹下的文件名/读取文件夹下图片名)
May 09 PHP
PHP 实现字符串翻转(包含中文汉字)的实现代码
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
无法载入 mcrypt 扩展,请检查 PHP 配置终极解决方案
2011/07/18 PHP
php 解压rar文件及zip文件的方法
2014/05/05 PHP
PHP实现自动识别Restful API的返回内容类型
2015/02/07 PHP
浅谈laravel中的关联查询with的问题
2019/10/10 PHP
JavaScript 给汉字排序实例代码
2008/06/28 Javascript
javascript与cookie 的问题详解
2013/11/11 Javascript
B/S模式项目中常用的javascript汇总
2013/12/17 Javascript
form表单action提交的js部分与html部分
2014/01/07 Javascript
JavaScript仿淘宝页面图片滚动加载及刷新回顶部的方法解析
2016/05/24 Javascript
vue-router:嵌套路由的使用方法
2017/02/21 Javascript
vue.js 1.x与2.0中js实时监听input值的变化
2017/03/15 Javascript
Angular2监听页面大小变化的解决方法
2017/10/09 Javascript
不使用 JS 匿名函数理由
2017/11/17 Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
2018/05/02 Javascript
vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单
2018/11/29 Javascript
小程序测试后台服务的方法(ngrok)
2019/03/08 Javascript
vue中的inject学习教程
2019/04/24 Javascript
vue指令做滚动加载和监听等
2019/05/26 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
2020/05/11 Javascript
echarts柱状图背景重叠组合而非并列的实现代码
2020/12/10 Javascript
基于Python执行dos命令并获取输出的结果
2019/12/30 Python
Python调用接口合并Excel表代码实例
2020/03/31 Python
印尼披萨外送专家:Domino’s Pizza印尼
2017/12/28 全球购物
车间班组长的职责
2013/12/13 职场文书
大课间活动制度
2014/01/18 职场文书
竞聘演讲稿
2014/04/24 职场文书
交通文明倡议书
2014/05/16 职场文书
乡镇群众路线专项整治方案
2014/11/03 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
有关三国演义的读书笔记
2015/06/25 职场文书
父亲节感言
2015/08/03 职场文书
售房协议书范本
2015/08/11 职场文书
创业方案:赚钱的烧烤店该怎样做?
2019/07/05 职场文书
经典法律座右铭(50句)
2019/08/15 职场文书
如何利用python和DOS获取wifi密码
2021/03/31 Python
html中相对位置与绝对位置的具体使用
2022/05/15 HTML / CSS