内容简介:Laravel 框架的事件机制
Laravel 框架的事件处理机制是通过类EventServiceProvider来实现的.
建立事件
首先我需要将自己的事件和监听者注册到app\Providers目录下的EventServiceProvider类中的$listen数组中
然后运行php artisan event:generate 命令会自动生成相应的事件类和监听者类。然后在相应的类中编写事件的逻辑和监听者的逻辑。调用事件可以使用 Event:: fire(new App\Events\TestEvent()) .这就是调用事件的基本步骤。具体请参考官方文档。
事件触发前
在服务提供者中,一般有register和boot方法,而boot方法一般在框架中已经注册完所有的服务提供者之后运行。而app\Providers目录下的EventServiceProvider类中的boot方法继承父类的boot方法。于是我们查看父类的boot方法如下:
public function boot() { foreach ($this->listens() as $event => $listeners) { foreach ($listeners as $listener) { Event::listen($event, $listener); } } foreach ($this->subscribe as $subscriber) { Event::subscribe($subscriber); } }
其实就是获取$listens属性数组并且进行遍历,将数组中的事件(键)和事件监听者(数组的键值)进行绑定。为了查看绑定的过程,我 们又要查看Event::listen 这个方法。由于调用的是facade,我们根据facade模式寻找到对应的类(facade模式原理请查看博文:http://blog.csdn.net/qq_16877261/article/details/77530081) \Illuminate\Events\Dispatcher找到listen方法如下:
public function listen($events, $listener) { foreach ((array)$events as $event) { if (Str::contains($event, '*')) { $this->setupWildcardListen($event, $listener); } else { $this->listeners[$event][] = $this->makeListener($listener); } } }
在这里我就不研究通配符形式的事件与事件监听者的绑定。于是其实代码通过
$this->listeners[$event][] = $this->makeListener($listener);
进行了绑定。我查看makeListener 方法如下:
public function makeListener($listener, $wildcard = false) { if (is_string($listener)) { return $this->createClassListener($listener, $wildcard); } return function ($event, $payload) use ($listener, $wildcard) { if ($wildcard) { return $listener($event, $payload); } else { return $listener(...array_values($payload)); } }; }
由于我们注册的事件监听者是字符串,代码运行到这一步。
return $this->createClassListener($listener, $wildcard);
于是跟踪函数代码如下:
public function createClassListener($listener, $wildcard = false) { //将监听者封装成闭包 return function ($event, $payload) use ($listener, $wildcard) { if ($wildcard) { return call_user_func($this->createClassCallable($listener), $event, $payload); } else { return call_user_func_array( $this->createClassCallable($listener), $payload ); } }; }
在这一步,函数将事件监听者封装成闭包的形式。在闭包里面通过如下代码实现了调用事件监听者的handle方法,以便在触发事件后调用闭包从而执行该方法。
return call_user_func_array( $this->createClassCallable($listener), $payload );
$this->createClassCallable($listener)
而这一步返回一个数组 [$listener,'handle'],通过call_user_func_array 函数实现了上述过程。
总结:在boot方法中实现事件监听者的注册与事件的绑定,而在注册与绑定过程中,将会封装一个闭包,并且在闭包中实现调用事件监听者类中的handle方法。
事件触发
事件触发采用如下形式:
Event::fire(new TestEvent());
在调用fire方法前,会实例化事件类,进行事件的逻辑操作。同样的我们在\Illuminate\Events\Dispatcher找到fire方法如下:
public function fire($event, $payload = [], $halt = false) { return $this->dispatch($event, $payload, $halt); }
其实fire方法调用的还是dispatch方法。
public function dispatch($event, $payload = [], $halt = false) { // When the given "event" is actually an object we will assume it is an event // object and use the class as the event name and this event itself as the // payload to the handler, which makes object based events quite simple. list($event, $payload) = $this->parseEventAndPayload( $event, $payload ); // -----------------------------这部分涉及广播系统,以后会详细讲解,这里就不讲解了。 if ($this->shouldBroadcast($payload)) { $this->broadcastEvent($payload[0]); } //------------------------------ $responses = []; foreach ($this->getListeners($event) as $listener) { //$listener 是一个闭包 $response = $listener($event, $payload); // If a response is returned from the listener and event halting is enabled // we will just return this response, and not call the rest of the event // listeners. Otherwise we will add the response on the response list. if (!is_null($response) && $halt) { return $response; } // If a boolean false is returned from a listener, we will stop propagating // the event to any further listeners down in the chain, else we keep on // looping through the listeners and firing every one in our sequence. if ($response === false) { break; } $responses[] = $response; } return $halt ? null : $responses; }
由于传进来的参数是实例化后的event 对象,所以在dispatch方法中首先通过parseEventAndPayload方法解析出字符串类型的事件名称和数组类型的(元素为事件对象)$payload 。然后根据事件名称 从之前保存过的
$this->listeners
数组中解析出监听者的闭包,然后通过闭包调用监听者类的handle方法。至此,事件机制原理讲解完了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 优秀开源框架的扩展机制实现
- Hadoop 框架:DataNode 工作机制详解
- 实时计算框架:Flink 集群搭建与运行机制
- PHP 开发框架 Notadd 发布 Beta5 版本,添加扩展机制
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
- 「前端面试题系列7」Javascript 中的事件机制(从原生到框架)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。