几句话熟悉 Laravel/Symfony 事件系统

我们知道,laravel/symfony框架是由一堆堆components组件粘合在一起的。其中会有一个event component组件,比较特殊,它像一个中介,是框架层全局component,专门负责不同component间相互通信传数据的。

说它是全局的,意思是,整个请求生命周期内,event 对象是单例的,每次从容器中获取标识为 'event' 的 event 对象还是最开始的event对象,为啥要这样搞啊?很简单啊,如果不是单例的,那第一个event对象里注册了10个事件,在其他某一个component里想要触发event对象里的一个发邮件事件'mail',但如果此时从容器中拿到的 event 对象不是原来的event 对象,那就找不到那个mail事件对应的事件处理器handler了。可以看看laravel的EventServiceProvider在往容器中注册标识为'event'对象时是使用的singleton()单例注册的,这样保证event对象永远是那一个。

说它负责跨组件通信,意思是比如对于database下的一个model对象如account model,当逻辑处理到save完一个account model到数据库时,如果需要再增加几个逻辑,如发个邮件mail,数据入数据库前需要验证validation,给这个account写个日志log等等,这几个逻辑需要Mail Component/Validation Component/Log Component里面的对象去处理,难道我要在$account->save()的后面在写一大坨这些逻辑?那代码岂不乱七八糟。何况我想在save前和save后再搞一些逻辑,那不完蛋了。有没有这样一种实践方式让我save前一两行代码,save后一两行代码,把这些逻辑解耦为各个小逻辑呢,这样代码岂不更清爽。

(1) 为啥需要事件系统?
代码层面,为了代码解耦,把在一处的一大坨逻辑解耦成多处细分代码,这样水平分层也符合单一职责原则,各个小模块干自己的那一小块任务,解耦出来的代码可读性远远大于糅合成一坨的代码可读性;性能考虑,事件的队列功能模拟了异步处理,把耗时的任务放在队列里,让队列一个个去慢慢处理这些任务。

(2) 事件架构是如何构成的?
事件架构其实很简单,它是一个框架层的全局component: event component,通过上面的描述知道它应该具备几个功能: 事件注册功能,事件触发功能,再加一个高级功能把事件放在队列里异步处理,如laravel里事件注册功能\\Illuminate\\Events\\Dispatcher::listen(),事件触发功能\\Illuminate\\Events\\Dispatcher::dispatch()。一个事件系统就这么简单,有兴趣有时间都可以自己写一个简单的事件系统了,当然,laravel/symfony 已经提供了比较好用的事件系统,小巧又好用,生产时还是用名家的产品呗。

(3) 一个事件event可以有多个处理器handler/listener,一个handler/listener可以监听多个事件,这个应该如何让event component支持呢?
要求多个handler/listener(一个callable或是一个class name)监听一个事件'event',很简单,那就多次注册\\Illuminate\\Events\\Dispatcher::listen($event_name, $handler),$event_name一样,$handler不一样而已,会按照注册顺序执行$handler,当然symfony支持在第三个参数就是priority,设置$handler执行顺序。
要求一个handler/listener可以监听多个event,很简单,把handler做成一个类class,然后里面做个$events数组属性设置要监听哪些events就行,laravel/symfony 都叫这个handler为Event Subscribers,仅此而已。

不想去画图来详细说明了,根据上面几句话,再去从架构层面去看laravel event/symfony event的事件系统文章,就很简单了,建议仔细阅读下官网这两篇文章,其他细节都是为了上面这些设计目的服务的,根据上面讲述的设计目的再去阅读这两篇文章,很容易明白一直以来的疑惑,laravel/symfony 事件系统到底是啥么?有啥用嗷?咋实现的啊?。。

说了这么多,一句话概括:事件系统就像是框架层的全局数据库,具有存储、注册和触发事件功能,水平分层去解耦代码,实现跨组件通信。。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 6年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

laravel用了symfony好多的组件

6年前 评论

@梦康 恩恩,这样也挺好,后端框架相互融合,相互学习,都不用吵架了,像前端那些框架那样,哈哈。

6年前 评论

symfony的事件系统设计的确实不错,简单也够用,laravel很多设计感觉已经过度了,很多第三方模块都感觉设计的很过度,什么玩意儿都拼命的往di里插,再牛逼的php这样玩也折腾不起吧

6年前 评论

@wangat 说的没错。总之,利用框架,又不局限于框架呗。

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!