怎么在请求 [结束] 时能捕捉到__destruct 里抛出的异常

2021-06-15 13:11:19 +08:00
 dzdh

__destruct里抛出异常已经不会产生致命错误了

场景是用户操作日志,laravel 框架,所有模型事件都实现了一个接口类ChangesLoggerInterface,然后当任意一个模型触发任意事件都会进到一个 ChangesLoggerListener的监听器中。

然后想实现:

当 saved\updated\deleted 的时候记录下哪些字段从 xx 改成了 bb 。

然后一次请求中肯定不止一个对象发生变动可能是多个比如电商下单接口可能会是order:saved,user:updated(last_order_dateline)

所以最终是实现在一次请求中记录一行数据(在 logs 表中)。

所以在 ChangesLoggerListener中 想调用一个 Logger的日志记录类,调用Logger::push,这样在当 Logger 触发__destruct的时候获取 $this->data(array) 拼成一行数据入库。

问题是:

__destruct必须是在refcount为 0 的时候才触发。所以如果业务逻辑里有 try...catch.. 的时候,实际上__destruct里的异常是不会被 catch 到的。

造成 refcount 不为 0 的原因是因为用了 Laravel 的 Facade 实现的接管的单例。

还有什么其他方案嘛?

1691 次点击
所在节点    PHP
12 条回复
Rache1
2021-06-15 14:26:52 +08:00
弄个类,然后存静态变量,在中间件后置获取这这个变量的内容,然后入库不就好了嘛
rockyliang
2021-06-15 14:45:10 +08:00
这个问题我没看太懂,我的理解是,你是想将数据表的增删改操作记录到日志里,但这个和在__destruct 里抛出异常有什么关系?
dzdh
2021-06-15 15:18:22 +08:00
@rockyliang

因为现在的方案是在一个 recorder 的__destruct 里做的,insert into log..... 但是如果这个处理失败会抛出异常(比如还有可能会创建异步任务,http rest 的 queue http 超时啥的会抛出异常)
dzdh
2021-06-15 15:18:43 +08:00
@faqqcn 也是个思路
dzdh
2021-06-15 15:19:57 +08:00
@faqqcn 甚至可以一个 provider 搞定
wangxin13g
2021-06-15 16:02:22 +08:00
不推荐用__destruct 来做任何事情,不熟悉 laravel,看你的说法应该得用类似 Hook 的机制而不是用__destruct
dzdh
2021-06-15 17:11:52 +08:00
@faqqcn

突然想到还是不行,因为监听的是 `saved/updated/deleted` 所以不能 更改操作成功了但是日志没记录上(比如因为异常)。
dzdh
2021-06-15 17:13:31 +08:00
@wangxin13g 的确是 hook,目前除了__destruct 想不到其他方案。比如 Laravel 的 dispatch()返回的 PendingDispatch 就是在 __destruct 的时候执行`queue::push`方法。
Rache1
2021-06-15 17:42:07 +08:00
@dzdh 那就注册一个异常处理器,然后去那里面处理噻
wangxin13g
2021-06-15 17:45:24 +08:00
@dzdh 那考虑一下加个消息队列解耦,消息体放更新前后数据,消费者消费消息生成日志。把日志放数据库的行为非常不好
dzdh
2021-06-16 09:05:58 +08:00
@faqqcn 但会脱离当前事务吧?会导致事务其实已经提交了。ExceptionHandler 里实际上是事务结束后的 Uncaught Exception
Rache1
2021-06-16 09:21:44 +08:00
@dzdh 那你在调用 $next($request) 外面包一个 try...catch 试试,把中间件优先级设置最前

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/783477

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX