分享一种Laravel异常上下文解决方案

发布时间 - 2021-01-21 00:00:00    点击率:

下面由Laravel教程栏目给大家介绍一种Laravel异常上下文解决方案,希望对需要的朋友有所帮助!

最近项目遇到一个情况,我们在遇到用户访问某个信息没有权限的时候,希望提示详细的原因,比如当访问一个团队资源时非成员访问的场景下会提示一个:您不是 [xxxxxx] 团队的成员,暂时无法查看,可,同时需要显示打码后的团队名称,以及加入按钮,可是接口方的逻辑是当没有权限时直接 abort 了:

abort_if(!$user->isMember($resouce->team), 403, '您无权访问该资源');

得到的响应结果如下:

HTTP/1.0 403 Forbidden{
    "message": "您无权访问该资源"}

我们不可能将 message 用 html 来完成前端提示页的展示,这样耦合性太强,违背了前后端分离的原则。我们的目标是返回如下的格式即可解决:

HTTP/1.0 403 Forbidden{
    "message": "您无权访问该资源",
    "team": {
        "id": "abxT8sioa0Ms",
        "name": "CoDesign****"
    }}

通过携带上下文的方法传递数据,方便了前端同学自由组合。

开始改造

当然这并不是什么复杂的事情,直接修改原来的 abort_if 即可解决:

- abort_if(!$user->isMember($resouce->team), 403, '您无权访问该资源');
+ if (!$user->isMember($resouce->team)) {
+    return response()->json([
+        'message' => '您无权访问该资源',
+        'team' => [
+            'id' => $resouce->team_id,
+            'name'=> $resouce->team->desensitised_name,
+        ]
+    ], 403);
+ }

这样看起来解决了问题,可是试想一下,如果是在闭包里面检测到异常想要退出,上面这种 return 式的写法就会比较难搞了,毕竟 return 只会终止最近的上下文环境,我们还是希望像 abort 一样能终止整个应用的执行,再进行另一番改造。

优化实现

看了 abort 源码,我发现它的第一个参数其实支持 \Symfony\Component\HttpFoundation\Response 实例,而上面我们 return 的结果就是它的实例,所以我们只需要改成这样就可以了:

 if (!$user->isMember($resouce->team)) {
    abort(response()->json([
        'message' => '您无权访问该资源',
        'team' => [
            'id' => $resouce->team_id,
            'name'=> $resouce->team->desensitised_name,
        ]
    ], 403));
 }

看起来实现了异常中断,可是新的问题来了,如果需要复用的时候还是比较尴尬,这段代码将会重复出现在各种有此权限判断的地方,这并不是我们想要的。

逻辑复用

为了达到逻辑复用,看了 \App\Exceptions\Handler 的实现,发现父类的 render 方法还有这么一个设计:

public function render($request, Throwable $e)
{
    if (method_exists($e, 'render') && $response = $e->render($request)) {
        return Router::toResponse($request, $response);
    } elseif ($e instanceof Responsable) {
        return $e->toResponse($request);
    }
    //...

所以,我们可以将这个逻辑抽离为一个独立的异常类,实现 render 方法即可:

我们先创建一个异常类:

$ ./artisan make:exception NotTeamMemberException

实现代码如下:

team = $team;
        parent::__construct($message, 403);
    }
    public function render()
    {
        return response()->json(
            [
                'message' => !empty($this->message) ? $this->message : '您无权访问该资源',
                'team' => [
                    'id' => $this->team->id,
                    'name' => $this->team->desensitised_name,
                ],
            ],
            403
        );
    }
}

这样一来,我们的逻辑就变成了:

if (!$user->isMember($resouce->team)) {
     throw new NotTeamMemberException($resouce->team, '您无权访问该资源');
}

当然也可以简写为:

\throw_if(!$user->isMember($resouce->team), NotTeamMemberException::class, $resouce->team, '您无权访问该资源');

问题到这里总算以一个比较完美的方式解决了,如果你有更好的方案欢迎评论探讨。


# laravel  # symfony  # html  # 父类  # 接口  # 闭包  # 您无权  # 看了  # 复用  # 这并  # 解决了  # 就会  # 是在  # 来了  # 第一个  # 将会 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  如何用y主机助手快速搭建网站?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中  ,南京靠谱的征婚网站?  大型企业网站制作流程,做网站需要注册公司吗?  如何解决hover在ie6中的兼容性问题  成都网站制作公司哪家好,四川省职工服务网是做什么用?  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  Laravel如何使用模型观察者?(Observer代码示例)  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  edge浏览器无法安装扩展 edge浏览器插件安装失败【解决方法】  网站建设整体流程解析,建站其实很容易!  Laravel如何使用Gate和Policy进行授权?(权限控制)  微信小程序 require机制详解及实例代码  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  Laravel API资源(Resource)怎么用_格式化Laravel API响应的最佳实践  如何在Windows服务器上快速搭建网站?  详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  Linux系统运维自动化项目教程_Ansible批量管理实战  如何在搬瓦工VPS快速搭建网站?  Laravel Fortify是什么,和Jetstream有什么关系  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制  如何在建站宝盒中设置产品搜索功能?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  高端网站建设与定制开发一站式解决方案 中企动力  如何用腾讯建站主机快速创建免费网站?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  焦点电影公司作品,电影焦点结局是什么?  如何批量查询域名的建站时间记录?  如何在万网ECS上快速搭建专属网站?  惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  用yum安装MySQLdb模块的步骤方法  Laravel如何实现API资源集合?(Resource Collection教程)  jQuery中的100个技巧汇总  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  昵图网官网入口 昵图网素材平台官方入口  EditPlus 正则表达式 实战(3)  高防服务器租用如何选择配置与防御等级?  jQuery 常见小例汇总  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  网站制作报价单模板图片,小松挖机官方网站报价?  Linux系统命令中tree命令详解