Dieser Artikel stellt hauptsächlich die Interpretation des Laravel-Ereignissystems vor, das einen gewissen Referenzwert hat. Jetzt kann ich es mit allen teilen, die es brauchen.
Laravel-Ereignisse eine einfache Beobachterimplementierung, die verschiedene in der Anwendung auftretende Ereignisse abonnieren und abhören kann. Der Ereignismechanismus ist eine gute Möglichkeit, Anwendungen zu entkoppeln, da ein Ereignis mehrere voneinander unabhängige Listener haben kann. Das Ereignissystem in laravel
besteht aus zwei Teilen. Der Name des Ereignisses kann eine Zeichenfolge sein, z. B. event.email
, oder eine Ereignisklasse, z. B. AppEventsOrderShipped
der Ereignis-Listenerlistener
, der ein Abschluss oder eine Listening-Klasse sein kann, wie z. B. AppListenersSendShipmentNotification
.
Wir verwenden weiterhin das in der offiziellen Dokumentation angegebene Beispiel, um die Quellcode-Implementierung des Ereignissystems zu analysieren. Bevor die Anwendung jedoch Ereignisse und Listener registriert, registriert Laravel zunächst die Ereignisverarbeitung, wenn die Anwendung gestartet wirdevents
Service.
Zu den grundlegenden Diensten, die beim Erstellen der Laravel-Anwendung registriert werden, gehört der Event
Dienst
namespace Illuminate\Foundation; 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)); } }
, zu dem EventServiceProvider
/Illuminate/Events/EventServiceProvider
< gehört 🎜 >
public function register() { $this->app->singleton('events', function ($app) { return (new Dispatcher($app))->setQueueResolver(function () use ($app) { return $app->make(QueueFactoryContract::class); }); }); }
ist die eigentliche Implementierungsklasse des IlluminateEventsDispatcher
-Dienstes, während die events
-Fassade der statische Proxy des Event
-Dienstes ist und ereignissystembezogene Methoden von events
bereitgestellt werden . IlluminateEventsDispatcher
Es gibt ein Array AppProvidersEventServiceProvider
, das alle Ereignisse (Schlüssel) und die den Ereignissen entsprechenden Listener (Werte) enthält, um alle Ereignis-Listener zu registrieren, und Sie können Ereignisse flexibel entsprechend Ihren Anforderungen hinzufügen. listen
/** * 应用程序的事件监听器映射。 * * @var array */ protected $listen = [ 'App\Events\OrderShipped' => [ 'App\Listeners\SendShipmentNotification', ], ];
-Methode der AppProvidersEventServiceProvider
-Klasse registrieren. boot
/** * 注册应用程序中的任何其他事件。 * * @return void */ public function boot() { parent::boot(); Event::listen('event.name', function ($foo, $bar) { // }); }
darin besteht, Ereignisse in der Anwendung zu registrieren. Die Hauptfunktion dieser Registrierungsklasse besteht darin, das Ereignissystem zu starten. AppProvidersEventProvider
IlluminateFoundationSupportProvidersEventServiceProvide
Als wir den Dienstanbieter hinzugefügt haben, haben wir gesagt, dass die Laravel-Anwendung nach der Registrierung aller Dienste diese Dienste startet, indem sie
Methoden aller Anbieter aufruft, also die Ereignisse in der Laravel-Anwendung und der Die Registrierung des Listeners erfolgt in der IlluminateFoundationBootstrapBootProviders
-Methode der boot
-Klasse. Schauen wir uns Folgendes an: IlluminateFoundationSupportProvidersEventServiceProvide
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); } }
boot
Sie können sehen, dass der Start des Ereignissystems durch die Listening- und Abonnementmethoden der Klasse erstellt wird Service-Ereignisse, entsprechende Listener und Ereignisabonnenten im System. 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); } }
events
Ereignisnamen, die Platzhalterzeichen enthalten, werden einheitlich in das Array eingefügt. wird zum Erstellen des wildcards
verwendet, das dem Ereignis entspricht: makeListener
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
Erstellen , wird beurteilt, ob das Hörobjekt eine Hörklasse oder eine Abschlussfunktion ist. listener
Für das Abhören von Abschlüssen umschließt
makeListener
Für die Listening-Klasse wird der Listener weiterhin über
class Dispatcher implements DispatcherContract { 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 ); } }; } protected function createClassCallable($listener) { list($class, $method) = $this->parseClassCallable($listener); if ($this->handlerShouldBeQueued($class)) { //如果当前监听类是队列的话,会将任务推送给队列 return $this->createQueuedHandlerCallable($class, $method); } else { return [$this->container->make($class), $method]; } } }
createClassListener
Für die Erstellung des Listeners über die Zeichenfolge der Listening-Klasse wird auch ein Abschluss zurückgegeben aktuelle Überwachung Wenn die Klasse eine Warteschlangenaufgabe ausführen soll, wird die Aufgabe nach der Ausführung durch den zurückgegebenen Abschluss in die Warteschlange verschoben. Wenn es sich um eine normale Überwachungsklasse handelt, erstellt die zurückgegebene Schließung das Überwachungsobjekt und führt die -Methode des Objekts aus. Daher gibt der Listener den Abschluss zurück, um den Kontext zu umschließen, wenn das Ereignis registriert wird, und ruft den Abschluss auf, um die Aufgabe auszuführen, während er auf die Auslösung des Ereignisses wartet. handle
Nachdem der Listener erstellt wurde, wird er im Array mit dem entsprechenden Ereignisnamen als Schlüssel im Array
entsprechen. 🎜>, genau wie das listener
-Array in der listener
-Klasse, als wir zuvor über das Beobachtermuster gesprochen haben, aber Laravel ist komplizierter. Sein listener
-Array zeichnet mehrere Subject
und entsprechende observers
-Korrespondenzen auf . listener
Subject
Ereignis auslösen观察者
stammt
public function fire($event, $payload = [], $halt = false) { return $this->dispatch($event, $payload, $halt); } public function dispatch($event, $payload = [], $halt = false) { //如果参数$event事件对象,那么就将对象的类名作为事件名称,对象本身作为携带数据的荷载通过`listener`方法 //的$payload参数的实参传递给listener list($event, $payload) = $this->parseEventAndPayload( $event, $payload ); if ($this->shouldBroadcast($payload)) { $this->broadcastEvent($payload[0]); } $responses = []; foreach ($this->getListeners($event) as $listener) { $response = $listener($event, $payload); //如果触发事件时传递了halt参数,并且listener返回了值,那么就不会再去调用事件剩下的listener //否则就将返回值加入到返回值列表中,等所有listener执行完了一并返回 if ($halt && ! is_null($response)) { return $response; } //如果一个listener返回了false, 那么将不会再调用事件剩下的listener if ($response === false) { break; } $responses[] = $response; } return $halt ? null : $responses; } protected function parseEventAndPayload($event, $payload) { if (is_object($event)) { list($payload, $event) = [[$event], get_class($event)]; } return [$event, Arr::wrap($payload)]; } //获取事件名对应的所有listener public function getListeners($eventName) { $listeners = isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : []; $listeners = array_merge( $listeners, $this->getWildcardListeners($eventName) ); return class_exists($eventName, false) ? $this->addInterfaceListeners($eventName, $listeners) : $listeners; }
Event::fire(new OrdershipmentNotification)
Nachdem das Ereignis ausgelöst wurde, werden alle events
-Abschlüsse, die dem Ereignisnamen entsprechen, aus dem vom zuvor registrierten Ereignis generierten gefunden und diese Abschlüsse werden dann aufgerufen, um Aufgaben im Listener-Hinweis auszuführen das:
Wenn der Ereignisnamenparameter ein Ereignisobjekt ist, wird der Klassenname des Ereignisobjekts als Ereignisname verwendet und selbst als Zeitparameter an den Listener übergeben.
Wenn der Stopp-Parameter beim Auslösen des Ereignisses übergeben wird und der Listener Nicht-false
zurückgibt, wird das Ereignis nicht weiter an die verbleibenden Listener weitergegeben, andernfalls wird es zurückgegeben Die Werte aller Listener werden nach der Ausführung aller Listener einheitlich als Array zurückgegeben.
Wenn ein Listener einen booleschen Wert zurückgibt false
, wird die Weitergabe des Ereignisses an die verbleibenden Listener sofort gestoppt.
Das Prinzip des Ereignissystems von Laravel ist immer noch das gleiche wie das zuvor erwähnte Beobachtermuster. Der Autor des Frameworks ist jedoch sehr geschickt und verwendet Schließungen geschickt, um das Ereignissystem zu implementieren Auch für Ereignisse, die eine Warteschlangenverarbeitung erfordern, können Anwendungsereignisse das Prinzip der Streuung von Bedenken nutzen, um die Codelogik in der Anwendung in einigen komplexeren Geschäftsszenarien effektiv zu entkoppeln. Natürlich sind Anwendungsereignisse nicht unter allen Umständen zum Schreiben von Code geeignet Ich habe zuvor einen Artikel über ereignisgesteuerte Programmierung geschrieben, um die Anwendungsszenarien von Ereignissen zu erläutern.
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich ist. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website.
Verwandte Empfehlungen:
Laravel-Benutzerauthentifizierungssystem (grundlegende Einführung)
Laravel 5.5 und höher, Multi-Umgebung Konfiguration lesen
Das obige ist der detaillierte Inhalt vonInterpretation des Laravel-Ereignissystems. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!