从头开始搭建Web框架(三)- 事件分发
从头开始搭建Web框架(三)- 事件分发

在上一篇文章中,介绍了MVC框架部分的最后一个部分:控制器,在这篇文章中,因为不讨论Model层的实现,所以介绍一下事件分发。

事件的分发,好比给软件系统预留的插孔,当我们需要增加部分逻辑时,则不需要修改整个整体部分,而是通过这个预留的插孔,插入对应的逻辑来实现,可以大大降低了代码的耦合性。

event-dispatcher

> composer require symfony/event-dispatcher

事件分发器,相当于整个流程中的一个调度员,通过监听注册的事件,然后触发对应的逻辑,中间件是一个比较好的例子,监听HTTP的请求,以处理对应的逻辑,比如:用户的验证,Log服务,响应数据的同一格式化处理等等。

下面的简易的例子,是判断用户IP,如果是127.0.0.1就显示被屏蔽的提示信息,这个逻辑放在控制器也是非常容易实现的,考虑到以后的扩展性,我们就正好使用事件分发的相关知识来实现这个功能。

在使用之前,新建两个目录EventsListeners,分别对应触发事件和监听器,不要忘了在composer.json中添加对应的autoload配置项。

"autoload": {
        "psr-4": {
            "Controller\\": "Controller/",
            "Listeners\\": "Listeners/",
            "Events\\": "Events/"
        }
    }

现在开始新建我们的第一个事件,请求事件,在Events中新建RequestEvent.php内容如下:

代码内容很简单,构造函数包含两个参数RequestResponse,然后包含两个get方法。

接着创建监听器,在Listeners中新建AuthListener.php文件:

这里就是包含着我们的业务逻辑代码,写在handle()函数之中。

有了触发事件和监听器,接下来我们便可以在index.php的入口文件中,进行事件的分发。

<?php

 $dispatcher->addListener('request', function(\Events\RequestEvent $requestEvent){
        $listeners = [
            \Listeners\AuthListener::class
        ];
        $request = $requestEvent->getRequest();
        $response = $requestEvent->getResponse();

        foreach($listeners as $listener){
            call_user_func_array([new $listener, 'handle'], [$request, $response]);
        }
    });
    

此段代码很容易理解,表示增加一个监听request事件的监听器,如果接收到,则通过回调函数将RequestEvent递交过来处理,为了保持可扩展性,并没有直接实例化AuthListener,而是将其放在数组中,遍历调用,当然你可以将其放在某个配置文件中读取过来,则是更加灵活的方式。

<?php

$dispatcher->dispatch('request', new \Events\RequestEvent($response, $request));

这里是显而易见的分发request事件,第一个参数是事件名,第二参数则是分发内容。需要注意的是,分发的操作一定要放在$response->send()之前,不在此之前整个生命周期就已经结束,再也无法触发了。

不出意外,重新刷新浏览器,会出现如下结果:

You have been banned

整个事件分发的开发就已经结束了,也非常之简单吧。

小结

至此,整个「从头开始搭建Web框架」的教程就已经结束,本教程不是对源代码的解析,只是粗略的从自己构建一个Web框架开始,让大家能够稍微理解一个框架的架构,所以代码难免会粗糙,剩下来的内容全凭读者自己去完成,这一方面节省了笔者大量的时间,另一方面能够留给大家足够动手的乐趣。

如果阅读完整个教程,你还有什么意见或者建议,都可以通过文章下面的联系方式,联系到我,最后,希望大家读完能够有所收获,(:

代码片段

所有代码已经托管到Github,地址:https://github.com/blue7wings/Ti-Framework

参考

https://symfony.com/doc/current/create_framework/event_dispatcher.html


If You Have Any Question, You Can Contact Me Through liam@blue7wings.com, @Blue7Wings, #Liam_Hsia