前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >优雅的输出错误-assert

优雅的输出错误-assert

作者头像
仙士可
发布2020-06-04 16:37:55
1.3K0
发布2020-06-04 16:37:55
举报
文章被收录于专栏:仙士可博客仙士可博客

在正常情况,我们会通过,if,else进行判断一个接口的条件是否满足,不满足则输出错误,例如

在IM系统中,申请入群接口,需要以下判断:

代码语言:javascript
复制
$param = $this->request()->getRequestParam();
$groupModel = new UserGroupModel();
//获取群信息
$groupInfo = $groupModel->getOneByGroupHash($param['groupHash']);
if (empty($groupInfo)){
    $this->writeJson(HttpStatus::CODE_BAD_REQUEST, [], '群组数据不存在');
    return true;
}
//判断被封
if($groupInfo->state!=1){
    $this->writeJson(HttpStatus::CODE_BAD_REQUEST, [], '群已经被封');
    return true;
}
//判断是否为本群成员
$groupUserModel = new GroupUserModel();
$userInfo = $groupUserModel->getOneByGroupIdAndUserId($groupInfo->groupId, $this->who->userId);
if ($userInfo){
    $this->writeJson(HttpStatus::CODE_BAD_REQUEST, [], '你已经是本群成员');
    return true;
}

可以看出,这里面有着非常多的if else,return,writeJson等重复代码.那么,有没有一个办法,进行if,else等封装,直接一行代码实现 判断+输出错误呢?

assert断言

断言是编程术语,表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真,可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言而在部署时禁用断言。

断言比较常见的场景在于unit单元测试,例如在easyswoole/redis组件中的tests 单元测试用例中:

仙士可博客
仙士可博客

在此示例中,可以看出,断言的作用在于确保程序的正常执行,如果出错则代表程序有问题,需要修bug 

业务断言

我们可以通过断言(确保其条件正确,使得程序往下执行)的说法,在业务中封装:

代码语言:javascript
复制
function assert($condition,$msg){
    //断言条件一定满足,不满足则抛出异常
    if ($condition!==true){
        throw new Exception($msg);      
    }
}

上面的代码优化:

代码语言:javascript
复制
$param = $this->request()->getRequestParam();
$groupModel = new UserGroupModel();
//获取群信息
$groupInfo = $groupModel->getOneByGroupHash($param['groupHash']);
//注意1:我们需要断言的是true,!!的作用是将正常数据转为bool类型
//断言一定存在groupInfo
assert(!!$groupInfo,'群组数据不存在');
//断言state一定为1
assert($groupInfo->state==1,'群组数据不存在');

//判断是否为本群成员
$groupUserModel = new GroupUserModel();
$userInfo = $groupUserModel->getOneByGroupIdAndUserId($groupInfo->groupId, $this->who->userId);
//断言一定不在群里
assert(!$userInfo,'你已经是本群成员');

在此时,我们已经将我们的判断代码,优化成了一行,在assert函数中,会将不符合预期的数据,通过异常抛出,我们需要通过拦截异常,来实现输出前端需要的数据格式:

代码语言:javascript
复制
try{
    $param = $this->request()->getRequestParam();
    $groupModel = new UserGroupModel();
    //获取群信息
    $groupInfo = $groupModel->getOneByGroupHash($param['groupHash']);
    //注意1:我们需要断言的是true,!!的作用是将正常数据转为bool类型
    //断言一定存在groupInfo
    assert(!!$groupInfo,'群组数据不存在');
    //断言state一定为1
    assert($groupInfo->state==1,'群组数据不存在');

    //判断是否为本群成员
    $groupUserModel = new GroupUserModel();
    $userInfo = $groupUserModel->getOneByGroupIdAndUserId($groupInfo->groupId, $this->who->userId);
    //断言一定不在群里
    assert(!$userInfo,'你已经是本群成员');

}catch (\Throwable $throwable){
    //拦截抛出的异常,然后直接输出json 错误消息
    $this->writeJson(HttpStatus::CODE_BAD_REQUEST, [], $throwable->getMessage());
    return true;
}

注意:上面的代码为简单实现,如果需要在项目中使用,请实现自定义异常类,捕捉自定义的异常,相关较为完善的代码已开源:

https://github.com/tioncico/LogicAssert  仅供参考

其他

需要注意的是,断言的意思为:  断定条件为真,使代码继续往下执行,断言抛出异常为,条件错误才抛出. 如果觉得拗口,可以改为logicCheck,直接判断为真则抛出异常即可

本文为仙士可原创文章,转载无需和我联系,但请注明来自仙士可博客www.php20.cn

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • assert断言
    • 业务断言
    • 其他
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档