资讯专栏INFORMATION COLUMN

如何优雅的设计PHP异常

wing324 / 3478人阅读

摘要:现在我就用框架来进行实战下在实际业务中是如何优雅的使用异常的场景描述选择一个比较简单的业务场景,以登录模块为例,用户在移动端进行登录时,需要进行登录,注册,忘记密码,获取手机验证码等接口。

前言

刚开始接触PHP的时候没有意识到异常的重要性,有时候出问题很难精确的找到问题点,正确的处理异常也是一门学问

异常的类别

PHP7异常做了很多变动,异常类 Exception 和错误类 Error 都实现了 Throwable 接口

结构如下:

Throwable

Error

ArithmeticError

DivisionByZeroError

AssertionError

ParseError

TypeError

ArgumentCountError

Exception

ClosedGeneratorException

DOMException

ErrorException

IntlException

LogicException

BadFunctionCallException

BadMethodCallException

DomainException

InvalidArgumentException

LengthException

OutOfRangeException

PharException

ReflectionException

RuntimeException

OutOfBoundsException

OverflowException

PDOException

RangeException

UnderflowException

UnexpectedValueException

SodiumException

什么时候才需要抛异常

这个一切从实际出发,如果你觉得你的代码可能会出现问题,就可以进行抛出异常

如何捕获异常

PHP中使用 try...catch...finally 捕获异常

public function test()
{
    try {
        //可能出错的代码逻辑
    } catch (Exception $e) {
        echo $e->getMessage();
    } finally {
        //todo
    }
}

如果不确定出现异常还是错误,可以直接捕获 Throwable 异常

public function test()
{
    try {
        //可能出错的代码逻辑
    } catch (Throwable $e) {
        echo $e->getMessage();
    } finally {
        //todo
    }
}
业务场景实战

现在的项目很多都是前后端分离、restful风格接口的设计进行开发。现在我就用tp5框架来进行实战下在实际业务中是如何优雅的使用异常的

场景描述

选择一个比较简单的业务场景,以登录模块为例,用户在移动端进行登录时,需要进行登录,注册,忘记密码,获取手机验证码等接口。

构建约束条件 登录

入参:

用户手机号

用户密码

手机验证码

约束:

用户手机号不能为空,格式正确,且此用户确实是存在的

密码不能为空,密码格式正确

手机验证码不能为空,且是在有效期内的

注册

入参:

用户手机号

用户密码

密码二次确认

手机验证码

约束:

用户手机号不能为空,格式正确,且此用户确实是新用户,系统不存在此用户信息

密码不能为空,密码格式正确

二次密码要跟密码一样

手机验证码不能为空,且是在有效期内的

忘记密码:

入参:

用户手机号

用户新密码

密码二次确认

手机验证码

约束:

用户手机号不能为空,格式正确,且此用户确实是存在的

密码不能为空,密码格式正确

二次密码要跟密码一样

手机验证码不能为空,且是在有效期内的

获取手机验证码

入参:

用户手机号

约束:

用户手机号不能为空,格式正确

一分钟内只能获取一次

自定义tp5异常 创建异常处理Handle类
# applicationlibexceptionExceptionHandle

namespace applicationlibexception;

use Exception;
use thinkexceptionHandle;

class ExceptionHandle extends Handle
{
    /**
     * @var $httpStatusCode http状态码
     */
    private $httpStatusCode;
    
    /**
     * @var $msg 错误信息
     */
    private $msg;
     
    /**
     * @var $code 错误码
     */
    private $code;

    # 自定义错误异常需要重写tp5父类的这个render方法
    public function render(Exception $e)
    {
        if ($e instanceof BaseException) {
            # 自定义异常
            $this->httpStatusCode = $e->httpStatusCode;
            $this->msg = $e->msg;
            $this->code = $e->code;
        } else {
            # 系统异常
            //TODO记录错误日志
            return parent::render($e)
        }
        
        $result = [
            "code" => $this->code,
            "msg" => $this->msg
        ];
        # 返回给前端
        return json($result, $this->httpStatusCode);
}
创建基础的异常类
# applicationlibexceptionBaseException

namespace applicationlibexception;

use thinkException;

# 异常类需要继承tp5的异常基类
class BaseException extends Exception
{
    public $httpStatusCode = 401;

    public $msg = "parameter error";
    
    public $code = 10000;
    
    public function __construct(array $params = [])
    {
        if (array_key_exists("httpStatusCode", $params)) {
            $this->httpStatusCode = $params["httpStatusCode"];
        }
        
        if (array_key_exists("msg", $params)) {
            $this->msg = $params["msg"];
        }
        
        if (array_key_exists("code", $params)) {
            $this->code = $params["code"];
        }
        
    }
}
创建具体异常类

参数错误异常类

namespace applibexception;

class ParameterException extends BaseException
{
    public $httpStatusCode = 200;

    public $msg = "parameter error";

    public $code = 10000;
}

用户不存在

class UserNotExistsException extends BaseException
{
    public $httpStatusCode = 200;

    public $msg = "user is not exists";

    public $code = 20000;
}
如何使用

我们先来看看登录这个功能

传统处理方法
public function login($phone, $password)
{
    $uid = $this->getUidByPhone($phone);
    if (!$uid) {
        # 进行处理
    }
}
通过异常处理
public function login($phone, $password)
{
    $uid = $this->getUidByPhone($phone);
    if (!$uid) {
        # 抛出异常,返回给前端
        throw new UserNotExistsException();
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/28486.html

相关文章

  • 深入理解PHP异常和错误处理(6)PHP如何优雅处理错误

    摘要:好了,终于写完了深入理解异常和错误处理这个系列了,可能大家平时使用框架开发,基本上不用考虑错误和异常,阅读,评论转发数量不尽人意,也可能自己水平有限本文由甲爪广告联盟整理编辑 前言:有错就改,错误光屏蔽是不行的,还需要对错误进行处理和记录。 内容概要: 1、顶层错误处理器的介绍2、示例代码 一、顶层错误处理器的介绍 php在处理错误的时候,可以简单的使用exit()和die()来进行基...

    Alliot 评论0 收藏0
  • PHPer这样写代码也许更优雅

    摘要:前言转眼间成为一名已经快整整两年了,在这期间也对如何写出可读性高,便于扩展的代码有了一些自己的想法。所以,我们在写上游代码时异常直接抛出即可。通常这样可以很大程度的提高效率和代码复用。 前言 转眼间成为一名PHPer已经快整整两年了,在这期间也对如何写出可读性高,便于扩展的代码有了一些自己的想法。 使用引用 场景一:遍历一个数组获取新的数据结构 也许你会这样写: // 申明一个新的数组...

    kidsamong 评论0 收藏0
  • 带你抛出优雅处理系统异常

    摘要:关于抛出异常如在我的上一篇文中所说的一样在接口的设计中接口的返回的数据是非常重要的例如无法避免的等等这些都是要命的错误同时还有一个极大的问题就是在新增模块中例如我最近需要新增一个的分词查询模块这个在添加索引删除索引等等操作的时候是非常容易导 showImg(http://pqykjwm6s.bkt.clouddn.com/Grassland_Scenery_by_Shi_Yuejun....

    susheng 评论0 收藏0
  • 分布式之API接口返回格式如何优雅设计

    摘要:区间表示参数错误区间表示用户错误区间表示接口异常这样前端开发人员在得到返回值后,根据状态码就可以知道,大概什么错误,再根据相关的信息描述,可以快速定位。享学课堂特邀作者:老顾前言在移动互联网,分布式、微服务盛行的今天,现在项目绝大部分都采用的微服务框架,前后端分离方式,(题外话:前后端的工作职责越来越明确,现在的前端都称之为大前端,技术栈以及生态圈都已经非常成熟;以前后端人员瞧不起前端人员,...

    phpmatt 评论0 收藏0
  • Laravel 程序架构设计思路:使用动作类

    摘要:一个动作类,应该有一个能够说明其功能的名字,比如等。如果需要对我们的动作类实现某种适配器模式,这是非常方便的。使用单动作类的好处小巧而单一的逻辑域能够防止代码重复并提高代码的可重用性,保持稳定。易于针对各种场景进行独立测试。 showImg(https://segmentfault.com/img/remote/1460000015208092); 当我们谈论到应用程序的架构的时候,经...

    Caicloud 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<