Ereignissystem


Event-System

Einführung in das Eventsystem

Laravel Das Ereignis stellt eine einfache Beobachterimplementierung bereit, die verschiedene in der Anwendung auftretende Ereignisse abonnieren und abhören kann. Ereignisklassen werden normalerweise im Verzeichnis app/Events gespeichert, und die Listener für diese Ereignisklassen werden im Verzeichnis app/Listeners gespeichert. Wenn Sie diese Verzeichnisse in Ihrer Anwendung nicht sehen, machen Sie sich keine Sorgen, sie werden automatisch erstellt, wenn Sie Artisan-Konsolenbefehle zum Generieren von Ereignissen und Listenern verwenden.

Das Ereignissystem bietet eine hervorragende Möglichkeit, verschiedene Aspekte der Anwendung zu entkoppeln, da ein einzelnes Ereignis mehrere voneinander unabhängige Listener haben kann. Beispielsweise möchten Sie Ihren Benutzern möglicherweise jedes Mal, wenn eine Bestellung versandt wird, eine Slack-Benachrichtigung senden. Anstatt Ihren Bestellabwicklungscode und den Slack-Benachrichtigungscode miteinander zu verknüpfen, können Sie einfach ein OrderShipped-Ereignis auslösen, das von einem Listener empfangen und in eine Slack-Benachrichtigung umgewandelt werden kann.

Registrieren von Ereignissen und Zuhörern

EventServiceProvider in der Laravel-Anwendung bietet die Registrierung aller Ereigniszuhörer einen bequemen Ort. Darunter enthält das Attribut listen ein Array aller Ereignisse (Schlüssel) und der den Ereignissen entsprechenden Listener (Werte). Natürlich können Sie je nach den Anforderungen Ihrer Anwendung mehrere Ereignisse zum im Attribut listen enthaltenen Array hinzufügen. Fügen wir zum Beispiel ein OrderShipped-Ereignis hinzu:

/**
 * 应用程序的事件监听器映射
 *
 * @var array
 */
 protected $listen = [ 
    'App\Events\OrderShipped' => [    
        'App\Listeners\SendShipmentNotification',  
        ],
    ];

Ereignisse und Listener generieren

Natürlich ist das manuelle Erstellen von Ereignis- und Listener-Dateien mühsam. Hier müssen Sie lediglich Listener und Ereignisse zu EventServiceProvider hinzufügen und dann den Befehl event:generate verwenden. Dieser Befehl generiert alle in EventServiceProvider aufgeführten Ereignisse und Listener. Selbstverständlich bleiben bereits bestehende Events und Zuhörer unverändert:

php artisan event:generate

Events manuell registrieren

Normalerweise sind Events registriert im EventServiceProvider-Array von $listen; Sie können sich jedoch auch in EventServiceProvider registrieren Registrieren Sie diese abschlussbasierten Ereignisse manuell in der boot-Methode:

/**
 * 注册应用中的其它事件
 *
 * @return void
 */
 public function boot(){ 
    parent::boot();    
    Event::listen('event.name', function ($foo, $bar) {  
          //   
       });
  }

Wildcard-Ereignis-Listener

Sie können * als Wildcard-Parameter verwenden, damit mehrere Ereignisse möglich sind auf demselben Listener erfasst. Ein Platzhalter-Listener erhält als erstes Argument den Ereignisnamen und als zweites Argument das gesamte Ereignisdatenarray:

Event::listen('event.*', function ($eventName, array $data) { 
   //
});

Ereignisse definieren

Die Ereignisklasse ist ein Container, der Informationen zum Ereignis speichert. Nehmen wir zum Beispiel an, dass das von uns generierte OrderShipped-Ereignis ein Eloquent ORM-Objekt empfängt:

<?php
    namespace App\Events;
    use App\Order;
    use Illuminate\Queue\SerializesModels;
    class OrderShipped{ 
       use SerializesModels;    
       public $order;    
     /**
     * 创建一个事件实例。
     *
     * @param  \App\Order  $order
     * @return void
     */   
    public function __construct(Order $order) 
       {    
           $this->order = $order;  
        }
    }

Wie Sie sehen können, ist in dieser Ereignisklasse keine andere Logik enthalten. Es handelt sich lediglich um einen Container für eine gekaufte Instanz von Order. Wenn Sie die serialize-Funktion von PHP verwenden, um ein Ereignisobjekt zu serialisieren, serialisiert das vom Ereignis verwendete Merkmal SerializesModels jedes Eloquent-Modell ordnungsgemäß.

Listener definieren

Als nächstes schauen wir uns die Listener für die Ereignisse im Beispiel an. Ereignis-Listener empfangen Instanzen in handle-Methoden. Der Befehl event:generate lädt automatisch die richtige Ereignisklasse und fügt den Ereignistyphinweis zur Methode handle hinzu. In der handle-Methode können Sie alle erforderlichen Aktionen als Reaktion auf das Ereignis ausführen:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    class SendShipmentNotification{  
      /**
     * 创建事件监听器。
     *
     * @return void
     */  
   public function __construct()
      {      
        // 
      }  
     /**
     * 处理事件。
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */ 
    public function handle(OrderShipped $event) 
       {    
           // 使用 $event->order 来访问 order ...  
        }
     }

{tip} Ihr Ereignis-Listener kann auch Typhinweise für alle Abhängigkeiten im Konstruktor hinzufügen. Alle Ereignis-Listener werden über den Service-Container von Laravel aufgelöst, sodass alle Abhängigkeiten automatisch eingefügt werden.

Ereignisweitergabe stoppen

Manchmal können Sie die Weitergabe von Ereignissen an andere Listener verhindern, indem Sie handle in der false-Methode Get des Listeners zurückgeben.

Ereignis-Listener-Warteschlange

Wenn Ihr Listener eine langsame Aufgabe ausführen muss, z. B. das Senden einer E-Mail oder das Senden einer HTTP-Anfrage, können Sie ihn zur Verarbeitung in die Warteschlange stellen. Bevor Sie mit der Verwendung eines Warteschlangen-Listeners beginnen, stellen Sie sicher, dass Sie Warteschlangen konfigurieren und einen Warteschlangen-Listener auf Ihrem Server oder Ihrer lokalen Entwicklungsumgebung starten können.

Um einen Listener zum Starten der Warteschlange anzugeben, können Sie die ShouldQueue-Schnittstelle zur Listener-Klasse hinzufügen. Der vom Artisan-Befehl event:generate generierte Listener hat diese Schnittstelle in den aktuellen Namespace importiert, sodass Sie sie direkt verwenden können:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{
        //
     }

Das ist es! Wenn dieser Listener von einem Ereignis aufgerufen wird, verwendet der Ereignis-Dispatcher automatisch das Warteschlangensystem von Laravel. Wenn beim Ausführen des Listeners in der Warteschlange keine Ausnahme ausgelöst wird, wird die Aufgabe nach Abschluss der Ausführung automatisch aus der Warteschlange gelöscht.

Benutzerdefinierte Warteschlangenverbindung und Warteschlangenname

Wenn Sie die Verbindung und den Namen der vom Ereignis-Listener verwendeten Warteschlange anpassen möchten, können Sie dies in der Listener-Klasse tun Definieren Sie $connection, $queue oder $delay Attribute:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{
       /**
     * The name of the connection the job should be sent to.
     *
     * @var string|null
     */  
   public $connection = 'sqs'; 
     /**
     * The name of the queue the job should be sent to.
     *
     * @var string|null
     */   
   public $queue = 'listeners';   
     /**
     * The time (seconds) before the job should be processed.
     *
     * @var int
     */ 
    public $delay = 60;
  }

Manueller Zugriff auf die Warteschlange

Wenn Sie manuell auf die Warteschlangenaufgabe unter dem Listener zugreifen müssen delete- und release-Methoden können Sie dies tun, indem Sie die Eigenschaft IlluminateQueueInteractsWithQueue verwenden. Diese Eigenschaft wird standardmäßig in den generierten Listener geladen und bietet Zugriff auf diese Methoden:

<?php
    namespace App\Listeners;
    use App\Events\OrderShipped;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{
        use InteractsWithQueue;  
      /**
     * 处理事件。
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */   
    public function handle(OrderShipped $event)
        {     
           if (true) { 
                  $this->release(30);  
                  }  
          }
     }

Behandlung fehlgeschlagener Aufgaben

Manchmal kann die Warteschlangenaufgabe eines Ereignis-Listeners fehlschlagen. Wenn die Warteschlangenaufgaben des Listeners die in der Warteschlange definierte maximale Anzahl von Versuchen überschreiten, wird die Methode failed auf dem Listener aufgerufen. Die failed-Methode empfängt eine Ereignisinstanz und die Ausnahme, die den Fehler verursacht hat, als Parameter:

<?php
    namespace App\Listeners;use App\Events\OrderShipped;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendShipmentNotification implements ShouldQueue{ 
       use InteractsWithQueue;   
       /**
     * 处理事件。
     *
     * @param  \App\Events\OrderShipped  $event
     * @return void
     */   
    public function handle(OrderShipped $event) 
       {    
           // 
        }  
    /**
     * 处理失败任务。
     *
     * @param  \App\Events\OrderShipped  $event
     * @param  \Exception  $exception
     * @return void
     */  
    public function failed(OrderShipped $event, $exception)
        {   
             //  
         }
     }

Versendet das Ereignis

Wenn Sie Ereignisse auslösen möchten, können Sie die Ereignisinstanz an die Hilfsfunktion event übergeben. Diese Hilfsfunktion verteilt das Ereignis an alle registrierten Listener, die dem Ereignis entsprechen. event Hilfsfunktionen können global verwendet werden und Sie können sie überall in Ihrer Anwendung aufrufen:

<?php
    namespace App\Http\Controllers;
    use App\Order;use App\Events\OrderShipped;
    use App\Http\Controllers\Controller;
    class OrderController extends Controller{   
       /**
     * 将传递过来的订单发货
     *
     * @param  int  $orderId
     * @return Response
     */   
   public function ship($orderId)
       {     
          $order = Order::findOrFail($orderId);        
          // 订单发货逻辑 ...        
          event(new OrderShipped($order));    
        }
       }

{tip} Beim Testen müssen Sie nur sicherstellen, dass ein bestimmtes Ereignis ausgelöst wird, ohne das tatsächlich auszulösen Hörer. Die integrierten Testhelfer von Laravel machen dies einfach.

Event-Abonnent

Ereignisabonnenten schreiben

Ereignisabonnenten sind Klassen, die mehrere Ereignisse in sich selbst abonnieren können, das heißt, sie können mehrere Ereignishandler in einer einzigen Klasse definieren. Abonnenten sollten eine subscribe-Methode definieren, die eine Event-Dispatcher-Instanz empfängt. Sie können Ereignis-Listener registrieren, indem Sie die Methode listen für einen bestimmten Ereignis-Dispatcher aufrufen:

<?php
    namespace App\Listeners;
    class UserEventSubscriber{  
      /**
     * 处理用户登录事件。
     */   
   public function onUserLogin($event) {}    
      /**
     * 处理用户注销事件。
     */   
   public function onUserLogout($event) {}   
    /**
     * 为订阅者注册监听器
     *
     * @param  \Illuminate\Events\Dispatcher  $events
     */   
    public function subscribe($events) 
       {      
         $events->listen(         
            'Illuminate\Auth\Events\Login',           
            'App\Listeners\UserEventSubscriber@onUserLogin'       
           );        
          $events->listen(         
             'Illuminate\Auth\Events\Logout',            
             'App\Listeners\UserEventSubscriber@onUserLogout'    
              );  
         }
      }

Register Event Subscriber

Nachdem Sie den Abonnenten geschrieben haben, können Sie den Abonnenten über den Event-Dispatcher registrieren. Sie können Abonnenten im EventServiceProvider-Attribut innerhalb von $subscribe registrieren. Fügen wir beispielsweise UserEventSubscriber zu einer Array-Liste hinzu:

<?php
    namespace App\Providers;
    use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
    class EventServiceProvider extends ServiceProvider{   
     /**
     * 应用中事件监听器的映射。
     *
     * @var array
     */   
   protected $listen = [  
         //  
        ];  
     /**
     * 需要注册的订阅者类。
     *
     * @var array
     */ 
    protected $subscribe = [ 
           'App\Listeners\UserEventSubscriber',   
          ];
      }
Dieser Artikel erschien zuerst auf der Website LearnKu.com.