分享一种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命令详解


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