Laravel 的事件提供了一个简单的观察者实现,能够订阅和监听应用中发生的各种事件。事件机制是一种很好的应用解耦方式,因为一个事件可以拥有多个互不依赖的监听器。laravel 中事件系统由两部分构成,一个是事件的名称,事件的名称可以是个字符串,例如 event.email,也可以是一个事件类,例如 App/Events/OrderShipped;另一个是事件的 监听器listener,可以是一个闭包,还可以是监听类,例如 App/Listeners/SendShipmentNotification。
我们还是通过官方文档里给出的这个例子来向下分析事件系统的源码实现,不过在应用注册事件和监听器之前,Laravel在应用启动时会先注册处理事件用的events服务。
Laravel注册事件服务Laravel应用在创建时注册的基础服务里就有Event服务
namespace Illuminate/Foundation;html' target='_blank'>class Application extends Container implements ... public function __construct($basePath = null) $this- registerBaseServiceProviders(); protected function registerBaseServiceProviders() $this- register(new EventServiceProvider($this)); $this- register(new LogServiceProvider($this)); $this- register(new RoutingServiceProvider($this));}
其中的 EventServiceProvider 是 /Illuminate/Events/EventServiceProvider
public function register() $this- app- singleton( events , function ($app) { return (new Dispatcher($app))- setQueueResolver(function () use ($app) { return $app- make(QueueFactoryContract::class);}
Illuminate/Events/Dispatcher 就是 events服务真正的实现类,而Event门面时events服务的静态代理,事件系统相关的方法都是由Illuminate/Events/Dispatcher来提供的。
应用中注册事件和监听我们还是通过官方文档里给出的这个例子来向下分析事件系统的源码实现,注册事件和监听器有两种方法,App/Providers/EventServiceProvider 有个 listen 数组包含所有的事件(键)以及事件对应的监听器(值)来注册所有的事件监听器,可以灵活地根据需求来添加事件。
/** * 应用程序的事件监听器映射。 * @var arrayprotected $listen = [ App/Events/OrderShipped = [ App/Listeners/SendShipmentNotification ,];
也可以在 App/Providers/EventServiceProvider 类的 boot 方法中注册基于事件的闭包。
/** * 注册应用程序中的任何其他事件。 * @return voidpublic function boot() parent::boot(); Event::listen( event.name , function ($foo, $bar) {}
可以看到/App/Providers/EventProvider类的主要工作就是注册应用中的事件,这个注册类的主要作用是事件系统的启动,这个类继承自 /Illuminate/Foundation/Support/Providers/EventServiceProvide。
我们在将服务提供器的时候说过,Laravel应用在注册完所有的服务后会通过/Illuminate/Foundation/Bootstrap/BootProviders调用所有Provider的boot方法来启动这些服务,所以Laravel应用中事件和监听器的注册就发生在 /Illuminate/Foundation/Support/Providers/EventServiceProvide类的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);}
可以看到事件系统的启动是通过events服务的监听和订阅方法来创建事件与对应的监听器还有系统里的事件订阅者。
namespace Illuminate/Events;class Dispatcher implements DispatcherContract 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); protected function setupWildcardListen($event, $listener) $this- wildcards[$event][] = $this- makeListener($listener, true);}
对于包含通配符的事件名,会被统一放入 wildcards 数组中,makeListener是用来创建事件对应的listener的:
class Dispatcher implements DispatcherContract 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));}
创建listener的时候,会判断监听对象是监听类还是闭包函数。
对于闭包监听来说,makeListener 会再包装一层返回一个闭包函数作为事件的监听者。
对于监听类来说,会继续通过 createClassListener 来创建监听者
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
新闻热点
疑难解答