PHP提供 Exception 类来处理异常

  1. new Exception('错误信息(默认为空)','错误代码(默认0)','异常链中前一个异常')

然后可以通过

  1. e -> getMessage() 获取异常信息
  2. e -> getCode() 获取异常错误码

处理异常

  1. try {
  2. //可能抛出异常代码
  3. throw new Exception("Error Processing Request", 1);
  4. } catch (Exception $e) {
  5. // 1. 记录日志
  6. // 2. 处理异常,程序继续进行 / 继续向上抛出异常 / 终止程序,打印异常错误
  7. }

在ThinkPHP中,框架自带异常处理类,返回错误信息以HTML页面形式展示,如果程序出现错误开发人员没有主动捕捉异常,则会被框架捕捉,然后抛出HTML

当在接口设计中时,由于无法得知客户端类型,所以HTML的形式客户端可能无法解析,此时便需要重写异常类,以json的形式返回错误信息给客户端

异常分类:

  • 自定义异常:通常是由客户端传递参数错误导致,此类异常不需要记录日志,但需要返回错误原因
  • 服务器异常:代码错误导致异常,此类异常需要记录日志,但不需要返回错误原因

服务器异常错误一般由PHP或者框架抛出,自定义异常需要手动捕捉,然后抛出

实现:

在Application/common目录下新建 exception 目录,此目录为异常类库目录

Application/common/exception/ExceptionHandler (重写后的异常处理类)

  1. <?php
  2. namespace app\common\exception;
  3.  
  4. use Exception;
  5. use think\exception\Handle;
  6. use think\facade\Request;
  7. use think\Log;
  8.  
  9. class ExceptionHandler extends Handle {
  10.  
  11. private $code;
  12. private $msg;
  13. private $errorCode;
  14.  
  15. public function render(Exception $e) {
  16. if ($e instanceof BaseException) {
  17. //如果是自定义异常,则控制http状态码,不需要记录日志
  18. //因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
  19. //不应当记录日志
  20.  
  21. $this->code = $e->code;
  22. $this->msg = $e->msg;
  23. $this->errorCode = $e->errorCode;
  24. } else {
  25. // 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
  26. if (config('app_debug')) {
  27. // 调试状态下需要显示TP默认的异常页面,因为TP的默认页面
  28. // 很容易看出问题
  29. return parent::render($e);
  30. }
  31.  
  32. $this->code = 500;
  33. $this->msg = 'sorry,we make a mistake. (^o^)Y';
  34. $this->errorCode = 999;
  35. $this->recordErrorLog($e);
  36. }
  37.  
  38. $request = Request::instance();
  39. $result = [
  40. 'msg' => $this->msg,
  41. 'error_code' => $this->errorCode,
  42. 'request_url' => $request = $request->url(),
  43. ];
  44. return json($result, $this->code);
  45. }
  46.  
  47. /*
  48. * 将异常写入日志
  49. */
  50. private function recordErrorLog(Exception $e) {
  51. Log::init([
  52. 'type' => 'File',
  53. 'path' => LOG_PATH,
  54. 'level' => ['error'],
  55. ]);
  56. Log::record($e->getMessage(), 'error');
  57. }
  58.  
  59. }

这个类会判断异常来源,并作出相应处理

创建处理类后,需要修改对应配置文件,让这个类成为框架默认异常处理类

在application/config/app.php

  1. // 异常处理handle类 留空使用 \think\exception\Handle
  2. 'exception_handle' => '\app\common\exception\ExceptionHandler',

Application/common/exception/BaseException (自定义异常类基类,基础PHP自带异常类Exception)

  1. <?php
  2. namespace app\common\exception;
  3. use think\Exception;
  4.  
  5. /**
  6. * Class BaseException
  7. * 自定义异常类的基类
  8. */
  9. class BaseException extends Exception {
  10. public $code = 400;
  11. public $msg = 'invalid parameters';
  12. public $errorCode = 999;
  13.  
  14. /**
  15. * 构造函数,接收一个关联数组
  16. * @param array $params 关联数组只应包含code、msg和errorCode,且不应该是空值
  17. */
  18. public function __construct($params = []) {
  19. if (!is_array($params)) {
  20. return;
  21. }
  22. if (array_key_exists('code', $params)) {
  23. $this->code = $params['code'];
  24. }
  25. if (array_key_exists('msg', $params)) {
  26. $this->msg = $params['msg'];
  27. }
  28. if (array_key_exists('errorCode', $params)) {
  29. $this->errorCode = $params['errorCode'];
  30. }
  31. }
  32. }

自定义异常类

Application/common/exception/UserException (自定义异常,这里举例User模块的异常)

  1. <?php
  2.  
  3. namespace app\common\exception;
  4.  
  5. class UserException extends BaseException {
  6. public $code = 404;
  7. public $msg = '用户不存在';
  8. public $errorCode = 60000;
  9. }

抛出自定义异常

  1. try {
  2. //todo...
  3. throw new \app\common\exception\UserException();
  4.  
  5. } catch (Exception $e) {
  6.  
  7. }

此时异常展示不再是TP自带的HTML页,而是

  1. {
  2. "msg": "用户不存在",
  3. "error_code": 60000,
  4. "request_url": "/wx_shop/public/index.php/admin/banner/list"
  5. }

  

PHP/TP5 接口设计中异常处理的更多相关文章

  1. 【RESTful风格】软件接口设计中RESTful风格

    REST = Representational State Transfer 表述性状态转移,是一种软甲接口设计风格.总之就是一种风格 REST基于:HTTP.HTML.JSON.XML.URI 这些 ...

  2. API 接口设计中 Token 类型的分类与设计

    在实际的网站设计中我们经常会遇到用户数据的验证和加密的问题,如果实现单点,如果保证数据准确,如何放着重放,如何防止CSRF等等 其中,在所有的服务设计中,都不可避免的涉及到Token的设计. 目前,基 ...

  3. python接口设计中的__all__和del

    最近在实现python接口中遇到了一些小问题,解决后总结如下. 目的:在设计接口时,只暴露某个文件的特定方法. 例如: t.py import os import sys def a(): pass ...

  4. TP5接口开发之异常处理接管

    前几天在开发的时候用到了第三方的扩展包,使用过程中第三方扩展包抛出了异常 因为这边是接口开发,需要返回错误代码以及提示信息等,所以就需要接管异常处理. 此文章只做笔记,有不对或不详细的地方欢迎大家留言 ...

  5. 在Java API设计中,面向接口编程的思想,以及接口和工厂的关系

    现在的java API的设计中,提倡面向接口的编程,即在API的设计中,参数的传递和返回建议使用接口,而不是具体的实现类,如一个方法的输入参数类型应该使用Map接口,而不是HashMap或Hashta ...

  6. C++ 11可变参数接口设计在模板编程中应用的一点点总结

    概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...

  7. 针对接口编程能帮助达到面向对象开发和设计中"低耦合"的要求. 某公司...打印机...(笔试中遇到的题目)

    针对接口编程能帮助达到面向对象开发和设计中"低耦合"的要求.         举个例子:某公司有一台特殊打印机,还可以使用一年,一年后可能换为另一种打印机,这两种打印机都特殊而贵. ...

  8. RESTful接口设计原则/最佳实践(学习笔记)

    RESTful接口设计原则/最佳实践(学习笔记) 原文地址:http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api 1 ...

  9. Web API接口设计经验总结

    在Web API接口的开发过程中,我们可能会碰到各种各样的问题,我在前面两篇随笔<Web API应用架构在Winform混合框架中的应用(1)>.<Web API应用架构在Winfo ...

随机推荐

  1. touchend偶尔不触发(待解决)

    新闻流,实现tab横向切换效果,出现偶尔切到一半,手指移开后,没有跳转到上一个或下一个tab,而是持续在当前切了一半的位置. 找到原因: 没有切换的时候,touchend都没有触发. 网上找到的解决办 ...

  2. iframe子页面控制父页面滚动高度,直接蹦到父页面开头

    zepto调用父页面窗口元素的scrollTop()方法会报错,貌似是scrollTop函数中有个scrollTo()方法用到this,指向错误. 经检查, 原生js控制父页面滚动,只能写数字,不能带 ...

  3. 基2时域抽取FFT、IFFT的C++实现代码,另附DFT与IDFT的原始实现--转1

    介绍网络上的原理介绍非常丰富,具体请自行搜索网络资源. 本算法依靠FFT流图进行布置. 算法 ##进行完所有的原理推导后,我们可以得到如下的16点FFT流图: 通过上图可以看出整个流图输入序列的顺序已 ...

  4. java面向对象编程(二)-构造方法(函数)

    1.类的构造方法介绍 什么是构造方法呢?在回答这个问题之前,我们来看一个需求:我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就直接指定 ...

  5. FCC JS基础算法题(2):Check for Palindromes(检查回文字符串)

    题目描述: 如果给定的字符串是回文,返回true,反之,返回false.如果一个字符串忽略标点符号.大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文).注意你需要去掉 ...

  6. 一十九条优雅Python编程技巧

    1.交换赋值 #不推荐 temp = a a = b b = a #推荐 a , b = b , a #先生成一个元组(tuple)对象,然后在unpack 2.Unpacking #不推荐 l = ...

  7. C++11 类型后置语法

    #include <iostream> #include <typeinfo> #include <type_traits> using namespace std ...

  8. SSM前言——相关设计模式

    1.使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑.客户类真正的想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象. 2.静态代理是指,代理类在程序运行前就已经定义好,其与目 ...

  9. Git删除分支/恢复分支

     • 删除一个已被终止的分支 如果需要删除的分支不是当前正在打开的分支,使用branch -d直接删除 git branch -d <branch_name> • 删除一个正打开的分支 如 ...

  10. sql语言 含有包含关系的查询 (含mysql 和sql sever)

    一.sql中查询包含关系的查询 sql语句中包含关系可以使用 in 和exist,但有些时候仅仅用这两个是不够的,还有表示方法是  not exist(b expect a )可以表示a包含b. 二. ...