Interpretation des Laravel-Ereignissystems

不言
Freigeben: 2023-04-02 17:00:01
Original
1976 Leute haben es durchsucht

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.

Ereignissystem

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 wirdeventsService.

Laravel-Registrierungsereignisdienst

Zu den grundlegenden Diensten, die beim Erstellen der Laravel-Anwendung registriert werden, gehört der EventDienst

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));
    }
}
Nach dem Login kopieren

, zu dem EventServiceProvider /Illuminate/Events/EventServiceProvider< gehört 🎜 >

public function register()
{
    $this->app->singleton(&#39;events&#39;, function ($app) {
        return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
            return $app->make(QueueFactoryContract::class);
        });
    });
}
Nach dem Login kopieren

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

Ereignisse registrieren und in der Anwendung abhören

Wir verwenden weiterhin das in der offiziellen Dokumentation angegebene Beispiel, um die Quellcode-Implementierung des Ereignissystems zu analysieren. Es gibt zwei Möglichkeiten, Ereignisse und Zuhörer zu registrieren.

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 = [
    &#39;App\Events\OrderShipped&#39; => [
        &#39;App\Listeners\SendShipmentNotification&#39;,
    ],
];
Nach dem Login kopieren

kann auch ereignisbasierte Abschlüsse in der

-Methode der AppProvidersEventServiceProvider-Klasse registrieren. boot

/**
 * 注册应用程序中的任何其他事件。
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Event::listen(&#39;event.name&#39;, function ($foo, $bar) {
        //
    });
}
Nach dem Login kopieren

Sie sehen, dass die Hauptaufgabe der Klasse

darin besteht, Ereignisse in der Anwendung zu registrieren. Die Hauptfunktion dieser Registrierungsklasse besteht darin, das Ereignissystem zu starten. AppProvidersEventProviderIlluminateFoundationSupportProvidersEventServiceProvideAls wir den Dienstanbieter hinzugefügt haben, haben wir gesagt, dass die Laravel-Anwendung nach der Registrierung aller Dienste diese Dienste startet, indem sie

die

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);
    }
}
Nach dem Login kopieren
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, &#39;*&#39;)) {
                $this->setupWildcardListen($event, $listener);
            } else {
                $this->listeners[$event][] = $this->makeListener($listener);
            }
        }
    }
    
    protected function setupWildcardListen($event, $listener)
    {
        $this->wildcards[$event][] = $this->makeListener($listener, true);
    }
}
Nach dem Login kopieren
eventsEreignisnamen, 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));
            }
        };
    }
}
Nach dem Login kopieren
listenerErstellen

, wird beurteilt, ob das Hörobjekt eine Hörklasse oder eine Abschlussfunktion ist.

listenerFür das Abhören von Abschlüssen umschließt

eine weitere Ebene und gibt eine Abschlussfunktion als Ereignis-Listener zurück.

makeListenerFü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];
        }
    }
}
Nach dem Login kopieren
createClassListenerFü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.

handleNachdem der Listener erstellt wurde, wird er im Array mit dem entsprechenden Ereignisnamen als Schlüssel im Array

platziert. Es können mehrere Arrays vorhanden sein, die einem Ereignisnamen 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 . listenerSubjectEreignis auslösen观察者

Sie können den Ereignisnamen oder die Ereignisklasse verwenden, um das Ereignis auszulösen. Verwenden Sie zum Auslösen des Ereignisses

, das ebenfalls vom

Dienst

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;
}
Nach dem Login kopieren
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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!