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 相关文章推荐
在IIS上安装PHP4.0正式版
Oct 09 PHP
PHP读取ACCESS数据到MYSQL的代码
May 11 PHP
在wamp集成环境下升级php版本(实现方法)
Jul 01 PHP
PHP OPP机制和模式简介(抽象类、接口和契约式编程)
Jun 09 PHP
浅谈PHP中output_buffering
Jul 13 PHP
Smarty高级应用之缓存操作技巧分析
May 14 PHP
PHP实现带重试功能的curl连接示例
Jul 28 PHP
利用php抓取蜘蛛爬虫痕迹的示例代码
Sep 30 PHP
php出租房数据管理及搜索页面
May 23 PHP
php 7新特性之类型申明详解
Jun 06 PHP
PHP 断点续传实例详解
Nov 11 PHP
laravel5.6 框架操作数据 Eloquent ORM用法示例
Jan 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与javascript实现变量交互的示例代码
2013/07/23 PHP
PHP根据传入参数合并多个JS和CSS文件的简单实现
2014/06/13 PHP
PHP中PDO的事务处理分析
2016/04/07 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
2018/12/21 PHP
PHP实现基于状态的责任链审批模式详解
2019/05/31 PHP
js left,right,mid函数
2008/06/10 Javascript
有关js的变量作用域和this指针的讨论
2010/12/16 Javascript
JavaScript 学习笔记之一jQuery写法图片等比缩放以及预加载
2012/06/28 Javascript
JS判断变量是否为空判断是否null
2014/07/25 Javascript
JavaScript Promise启示录
2014/08/12 Javascript
JavaScript控制图片加载完成后调用回调函数的方法
2015/03/20 Javascript
Javascript对象Clone实例分析
2015/06/09 Javascript
JavaScript检测并限制复选框选中个数的方法
2015/08/12 Javascript
JavaScript学习小结之使用canvas画“哆啦A梦”时钟
2016/07/24 Javascript
在微信、支付宝、百度钱包实现点击返回按钮关闭当前页面和窗口的方法
2016/08/05 Javascript
jQuery的deferred对象使用详解
2016/09/25 Javascript
浅谈JS函数节流防抖
2017/10/18 Javascript
js图片无缝滚动插件使用详解
2020/05/26 Javascript
video.js添加自定义组件的方法
2020/12/09 Javascript
使用python实现baidu hi自动登录的代码
2013/02/10 Python
Perl中著名的Schwartzian转换问题解决实现
2015/06/02 Python
Python2.7编程中SQLite3基本操作方法示例
2017/08/09 Python
Python 反转字符串(reverse)的方法小结
2018/02/20 Python
Django + Uwsgi + Nginx 实现生产环境部署的方法
2018/06/20 Python
python opencv实现旋转矩形框裁减功能
2018/07/25 Python
基于Python获取城市近7天天气预报
2019/11/26 Python
解决python -m pip install --upgrade pip 升级不成功问题
2020/03/05 Python
HTML5 visibilityState属性详细介绍和使用实例
2014/05/03 HTML / CSS
挪威太阳镜和眼镜网上商城:SmartBuyGlasses挪威
2016/08/20 全球购物
波兰最早的运动鞋精品店之一:Street Supply
2019/08/29 全球购物
家居设计专业个人自荐信范文
2013/11/26 职场文书
售后服务经理岗位职责范本
2014/02/22 职场文书
党的群众路线教育实践活动个人整改方案
2014/10/25 职场文书
运动会200米广播稿
2015/08/19 职场文书
python生成随机数、随机字符、随机字符串
2021/04/06 Python
浅析Django接口版本控制
2021/06/26 Python