PHP提供 Exception 类来处理异常

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

然后可以通过

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

处理异常

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

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

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

异常分类:

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

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

实现:

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

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

<?php
namespace app\common\exception; use Exception;
use think\exception\Handle;
use think\facade\Request;
use think\Log; class ExceptionHandler extends Handle { private $code;
private $msg;
private $errorCode; public function render(Exception $e) {
if ($e instanceof BaseException) {
//如果是自定义异常,则控制http状态码,不需要记录日志
//因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
//不应当记录日志 $this->code = $e->code;
$this->msg = $e->msg;
$this->errorCode = $e->errorCode;
} else {
// 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
if (config('app_debug')) {
// 调试状态下需要显示TP默认的异常页面,因为TP的默认页面
// 很容易看出问题
return parent::render($e);
} $this->code = 500;
$this->msg = 'sorry,we make a mistake. (^o^)Y';
$this->errorCode = 999;
$this->recordErrorLog($e);
} $request = Request::instance();
$result = [
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $request = $request->url(),
];
return json($result, $this->code);
} /*
* 将异常写入日志
*/
private function recordErrorLog(Exception $e) {
Log::init([
'type' => 'File',
'path' => LOG_PATH,
'level' => ['error'],
]);
Log::record($e->getMessage(), 'error');
} }

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

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

在application/config/app.php

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

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

<?php
namespace app\common\exception;
use think\Exception; /**
* Class BaseException
* 自定义异常类的基类
*/
class BaseException extends Exception {
public $code = 400;
public $msg = 'invalid parameters';
public $errorCode = 999; /**
* 构造函数,接收一个关联数组
* @param array $params 关联数组只应包含code、msg和errorCode,且不应该是空值
*/
public function __construct($params = []) {
if (!is_array($params)) {
return;
}
if (array_key_exists('code', $params)) {
$this->code = $params['code'];
}
if (array_key_exists('msg', $params)) {
$this->msg = $params['msg'];
}
if (array_key_exists('errorCode', $params)) {
$this->errorCode = $params['errorCode'];
}
}
}

自定义异常类

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

<?php

namespace app\common\exception;

class UserException extends BaseException {
public $code = 404;
public $msg = '用户不存在';
public $errorCode = 60000;
}

抛出自定义异常

    try {
//todo...
throw new \app\common\exception\UserException(); } catch (Exception $e) { }

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

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

  

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. Layer For Mobile 弹窗 input输入文字后,点击取消确定按钮失效(需点击两次)

    webapp中使用Layer For Mobile弹出弹窗,修改昵称输入文字后,ios手机中,如果不先点击收起键盘,两个按钮点击之后无效... 两个按钮的方法是写在这里的——> 最后只能吧点击按 ...

  2. guava-retrying 源码解析(导入项目)

    1.从github上下载guava-retry源码 git clone git://github.com/rholder/guava-retrying.git 2.导入idea,使用gradle记得勾 ...

  3. 深入理解Java并发synchronized同步化的代码块不是this对象时的操作

    本文仅仅是为了说明synchronized关键字同步的是对象不是方法,列子的确有失偏颇. 一.明确一点synchronized同步的是对象不是方法也不是代码块  我有关synchronized同步的是 ...

  4. shell命令记录

    1. 过滤注释和空行 cat /etc/rsyslog.conf|grep -v "#"  |  grep -v "^$" 2. flume日志采集: for ...

  5. 什么是node

    node 编辑 锁定讨论999 本词条缺少概述图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!   node(结点):网络连接的端点,或两条(或多条)线路的连接点.结点可以是处理器.控制器或 ...

  6. c——根据天数输出日期

    <c语言程序设计>(第三版)何钦铭 P190 #include<stdio.h> void month_day(int year,int yearday,int *pmonth ...

  7. Introduction of filter in servlet

    官方给出的Filter的定义是在请求一个资源或者从一个资源返回信息的时候执行过滤操作的插件.我们使用过滤起最多的场景估计就是在请求和返回时候的字符集转换,或者权限控制,比如一个用户没有登录不能请求某些 ...

  8. C# EasyHook MessageBox 示例(极简而全)

    完整代码,原创无藏私,绝对实用.Windows10 X64 下调试通过,对 w3wp.exe, sqlserver.exe,notepad.exe,iexporer.exe 注入后,长时间运行稳定,未 ...

  9. java_GC

    垃圾回收1    内存分配    垃圾回收    调用垃圾回收器    对象终结            调用垃圾回收器        System.gc()和Runtime.getRuntime(). ...

  10. Java自定义类加载器与双亲委派模型

    其实,双亲委派模型并不复杂.自定义类加载器也不难!随便从网上搜一下就能搜出一大把结果,然后copy一下就能用.但是,如果每次想自定义类加载器就必须搜一遍别人的文章,然后复制,这样显然不行.可是自定义类 ...