Yii框架中为什么应该提供全局事件

之前已经写了蛮多的跟这个事件驱动特性有关的内容了。比如我今天发现,Yii 框架支持的事件驱动,只能支持对对象实例进行事件绑定。简单来说,当你要绑定某个事件的时候,这个事件的触发者的对象,必须已经建立好了。

之前,我们聊过,事务应该尽可能写在 Model 里,而跟其他的无关。对于有些业务场景,构造某种对象,本身就是一个业务。因为构造这个对象太过有特点,以至于,我认为应该也封装在 Model 里面供别的业务去复用。

这个时候,如果碰巧有个业务要在该对象构造的时候,触发某个行为,那么总不能把事件绑定到 Model 里面去,这就显得很奇怪了。

举个具体的例子,比如我现在开发一个功能,就是用户要下订单。但是,订单可以被创建出来,是要检查很多条件的,而且跟库存之类的信息都高度相关,所以,我把整个业务封装起来了。

这时候,系统要求搞个活动,在创建订单的时候,如果订单满足条件,就给订单用户一定奖励。所以,我们在订单创建成功的时候,应该能够触发一个检查,判定活动的条件。

最坏的写法,就是把这个检查,直接写到订单的类里面,创建订单的业务里面。次之,就是把代码写到创建订单的 Controller 里,这样创建完毕的时候,直接执行检查就行了。

而我认为最好的写法,就是单独写个活动的类,通过配置文件,在系统启动的时候,注册一个事件,监听新订单创建的事件,然后在活动类里,去实现一个事件处理器,针对活动条件进行检查,如果通过,就应用活动奖励,否则就放弃。

这样,对于订单创建的 Controller 也好,订单的 Model 也好,根本就没必要知道活动的存在。也不必要去修改相关的业务了。以后,有任何其他活动,只要注册其他的活动类进去就行了。

但是,整个 Yii 框架,就没有提供这个机制,比如,在系统启动的时候,任何对象都还没有创建,这个时候,根本没法进行事件的绑定,所以整体来说,这个问题还蛮困扰我的。

最后,我的方法,就是自己实现了一个事件的 Dispatcher,然后可以通过配置文件来注册事件处理器,然后,在所有关键业务里,都触发事件。在没有任何对象构造出来的时候,就可以绑定事件处理器,一旦事件触发,就能执行对应的代码,从而实现对关键业务和核心业务代码的稳定性的维持。