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读写文件的方法(生成HTML)
Nov 27 PHP
php 服务器调试 Zend Debugger 的安装教程
Sep 25 PHP
php 智能404跳转代码,适合换域名没改变目录的网站
Jun 04 PHP
phpmyadmin显示utf8_general_ci中文乱码的问题终级篇
Apr 08 PHP
PHP 处理TXT文件(打开/关闭/检查/读取)
May 13 PHP
PHP获取服务器端信息的方法
Nov 28 PHP
PHP实现HTML页面静态化的方法
Nov 04 PHP
在WordPress中实现发送http请求的相关函数解析
Dec 29 PHP
关于PHP 如何用 curl 读取 HTTP chunked 数据
Feb 26 PHP
php 静态属性和静态方法区别详解
Apr 09 PHP
PDO::inTransaction讲解
Jan 28 PHP
laravel 根据不同组织加载不同视图的实现
Oct 14 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
PHP5 安装方法
2007/01/15 PHP
PHP 一个随机字符串生成代码
2010/05/26 PHP
php生成百度sitemap站点地图类函数实例
2014/10/17 PHP
yii框架无限极分类的实现方法
2017/04/08 PHP
Laravel登录失败次数限制的实现方法
2020/08/26 PHP
js 加载时自动调整图片大小
2008/05/28 Javascript
js showModalDialog弹出窗口实例详解
2014/01/07 Javascript
JavaScript利用append添加元素报错的解决方法
2014/07/01 Javascript
js实现九宫格图片半透明渐显特效的方法
2015/02/16 Javascript
Javascript中使用A标签获取当前目录的绝对路径方法
2015/03/02 Javascript
使用window.prompt()实现弹出用户输入的对话框
2015/04/13 Javascript
jQuery实现带有上下控制按钮的简单多行滚屏效果代码
2015/09/04 Javascript
老生常谈js中0到底是 true 还是 false
2017/03/08 Javascript
VUE中v-model和v-for指令详解
2017/06/23 Javascript
Node.js 中使用 async 函数的方法
2017/11/20 Javascript
node.js express框架简介与实现
2019/07/23 Javascript
一看就会的vuex实现登录验证(附案例)
2020/01/09 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
[02:27]2018DOTA2亚洲邀请赛趣味视频之钓鱼大赛 谁是垂钓冠军?
2018/04/05 DOTA
pyttsx3实现中文文字转语音的方法
2018/12/24 Python
详解python中init方法和随机数方法
2019/03/13 Python
python实现word文档批量转成自定义格式的excel文档的思路及实例代码
2020/02/21 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
matplotlib教程——强大的python作图工具库
2020/10/15 Python
Python实现随机爬山算法
2021/01/29 Python
如何用python爬取微博热搜数据并保存
2021/02/20 Python
详解Html5中video标签那些属性和方法
2019/07/01 HTML / CSS
联想阿根廷官方网站:Lenovo Argentina
2019/10/14 全球购物
自动化专业本科毕业生求职信
2013/10/20 职场文书
夜不归宿检讨书
2014/02/25 职场文书
股权转让意向书
2014/04/01 职场文书
2015大学生实训报告
2014/11/05 职场文书
初中作文评语集锦
2014/12/25 职场文书
驳回起诉民事裁定书
2015/05/19 职场文书
《用字母表示数》教学反思
2016/02/17 职场文书
Python可变集合和不可变集合的构造方法大全
2021/12/06 Python