Start · Sprachen · PHP · Referenz · Event

Event

Klasse

Repräsentiert ein I/O-, Timer- oder Signal-Ereignis innerhalb der <code>libevent</code>-Erweiterung und ermöglicht asynchrone, ereignisgesteuerte Programmierung in PHP.

seit PHP 1.1.0 Kategorie: io

Signatur

class Event

Beschreibung

Die Klasse Event ist Teil der PECL-Event-Erweiterung und bildet die Kernabstraktion der libevent-Bibliothek. Ein Objekt dieser Klasse repräsentiert ein einzelnes Ereignis, das auf einem Dateideskriptor (Socket, Pipe, reguläre Datei), einem Timer oder einem Betriebssystem-Signal basiert. Sobald das Ereignis eintritt, wird eine registrierte Callback-Funktion aufgerufen.

Ereignisse können pegelgesteuert (level-triggered) oder flankengesteuert (edge-triggered, Flag Event::ET) sein. Bei pegelgesteuerten Ereignissen wird der Callback so lange wiederholt aufgerufen, wie der Zustand (z. B. Daten im Puffer) anhält; bei flankengesteuerten Ereignissen nur dann, wenn ein Zustandswechsel eintritt. Flankengesteuerte Modi sind effizienter, erfordern aber sorgfältigeres Puffermanagement.

Ein Event-Objekt muss einer EventBase-Instanz zugeordnet und explizit aktiviert werden (Event::add()), bevor es überwacht wird. Typische Einsatzgebiete sind hochperformante Netzwerkserver, asynchrone HTTP-Clients, Datenbankverbindungspools und jede Anwendung, die viele gleichzeitige I/O-Operationen ohne Threads verwalten muss.

  • Lese-/Schreibereignisse: Reagieren, sobald ein Deskriptor lesbar oder schreibbar ist (Event::READ, Event::WRITE).
  • Timer-Ereignisse: Einmalige oder wiederkehrende Zeitgeber ohne Dateideskriptor.
  • Signal-Ereignisse: Asynchrones Abfangen von POSIX-Signalen (Event::SIGNAL).

Parameter

Name Typ Default Beschreibung
$base Pflicht EventBase Die EventBase-Instanz, der dieses Ereignis zugeordnet wird. Alle Ereignisse einer Anwendung teilen sich typischerweise eine gemeinsame Basis.
$fd Pflicht mixed Der zu überwachende Dateideskriptor oder Socket (PHP-Resource), oder -1 für Timer-Ereignisse bzw. ein Signal-Deskriptor bei Signal-Ereignissen.
$what Pflicht int Bitmaske der Ereignisflags. Mögliche Werte: Event::READ, Event::WRITE, Event::SIGNAL, Event::TIMEOUT, Event::PERSIST (wiederholt auslösen), Event::ET (flankengesteuert).
$cb Pflicht callable Die Callback-Funktion, die aufgerufen wird, wenn das Ereignis eintritt. Signatur: function(mixed $fd, int $what, mixed $arg): void.
$arg mixed null Optionaler benutzerdefinierter Wert, der unverändert als drittes Argument an den Callback übergeben wird (z. B. Kontext-Objekt oder Verbindungsstruktur).

Rückgabewert

Typ

Beispiele

Einfacher TCP-Echo-Server mit Event::READ und Event::PERSIST

<?php
// Voraussetzung: PECL-Erweiterung 'event' installiert

$base = new EventBase();

$server = stream_socket_server('tcp://0.0.0.0:8080', $errno, $errstr);
stream_set_blocking($server, false);

// Akzeptiere neue Verbindungen
$acceptEvent = new Event($base, $server, Event::READ | Event::PERSIST, function ($fd) use ($base) {
    $conn = stream_socket_accept($fd);
    if (!$conn) {
        return;
    }
    stream_set_blocking($conn, false);

    // Für jede Verbindung ein eigenes Lese-Ereignis erzeugen
    $readEvent = new Event($base, $conn, Event::READ | Event::PERSIST, function ($fd, $what, $ev) {
        $data = fread($fd, 4096);
        if ($data === false || $data === '') {
            $ev->del();
            fclose($fd);
            return;
        }
        fwrite($fd, $data); // Echo zurückschicken
    });
    $readEvent->add();
    // Referenz halten, damit GC das Objekt nicht zerstört
    $GLOBALS['events'][] = $readEvent;
});

$acceptEvent->add();
echo "Echo-Server lauscht auf Port 8080...\n";
$base->loop();
Echo-Server lauscht auf Port 8080...

Periodischer Timer mit Event::TIMEOUT und Event::PERSIST

<?php
$base = new EventBase();
$counter = 0;

// Timer-Ereignis: kein Dateideskriptor (-1), nur TIMEOUT | PERSIST
$timer = new Event($base, -1, Event::TIMEOUT | Event::PERSIST, function () use (&$counter, &$timer, $base) {
    $counter++;
    echo "Tick #{$counter} um " . date('H:i:s') . "\n";
    if ($counter >= 3) {
        $timer->del(); // Nach 3 Ticks stoppen
        $base->exit();  // Event-Loop beenden
    }
});

// Alle 1000 ms (1 Sekunde) auslösen
$timer->add(1.0);
$base->loop();
echo "Timer beendet.\n";
Tick #1 um 12:00:01 Tick #2 um 12:00:02 Tick #3 um 12:00:03 Timer beendet.

// Wichtig · Fallstricke

Lebenszyklus: Ein Event-Objekt bleibt nur so lange aktiv, wie eine PHP-Variable eine Referenz darauf hält. Wird das Objekt vom Garbage Collector freigegeben, wird das Ereignis automatisch deregistriert – ein häufiger Fehler ist, das Objekt in einer lokalen Variable zu erzeugen und dann aus dem Scope zu verlieren.

Nicht-blockierender Modus: Alle Dateideskriptoren, die mit Event überwacht werden, müssen in den nicht-blockierenden Modus versetzt werden (z. B. via stream_set_blocking($fd, false)), da sonst der gesamte Event-Loop blockiert.

Flankengesteuert (Event::ET): Wird nur von bestimmten Backends (epoll, kqueue) unterstützt. Im flankengesteuerten Modus muss der Callback den Puffer vollständig leeren, da sonst keine weiteren Ereignisse ausgelöst werden.

Signale: Signal-Ereignisse sind nur auf POSIX-Systemen verfügbar und sollten nicht mit PHPs eingebautem pcntl_signal() kombiniert werden, da es zu Konflikten kommen kann.