W3docs

ignore_user_abort()

In diesem Artikel erläutern wir die PHP-Funktion ignore_user_abort(), ihre Funktionsweise und zeigen Beispiele für ihre Verwendung.

Die PHP-Funktion ignore_user_abort() steuert, ob ein Skript weiterläuft, nachdem der Client (der Browser des Benutzers) die Verbindung getrennt hat. Diese Seite erläutert, was die Funktion tut, ihre Signatur und ihren Rückgabewert, wie sie zusammen mit connection_aborted() funktioniert, häufige Fallstricke und ein vollständiges Beispiel für Hintergrundaufgaben.

Was ignore_user_abort() bewirkt

Wenn ein Benutzer den Browser-Tab schließt, auf Stopp drückt oder die Seite verlässt, wird die Verbindung zum Server getrennt. Standardmäßig stoppt PHP das Skript nicht sofort in diesem Moment — es bemerkt die unterbrochene Verbindung erst beim nächsten Versuch, Ausgabe an den Browser zu senden, woraufhin das Skript beendet wird. ignore_user_abort() ändert dieses Verhalten: Mit aktivierter Funktion führt PHP das Skript bis zum Ende aus, auch wenn niemand mehr zuhört.

Dies ist wichtig für Operationen, die nicht halb abgeschlossen hinterlassen werden dürfen — das Schreiben in eine Datenbank, die Verarbeitung einer Zahlung, das Senden einer E-Mail oder das Erstellen eines Berichts. Wenn der Benutzer mittendrin die Verbindung trennt, soll die Arbeit in der Regel abgeschlossen werden, anstatt das System in einem inkonsistenten Zustand zu hinterlassen.

Ein „Client-Abbruch" ist ein Ereignis auf Transportebene: PHP erkennt ihn nur, wenn es versucht, in eine bereits geschlossene Verbindung zu schreiben. Deshalb fühlt sich das Timing indirekt an — siehe Warum der Abbruch spät erkannt wird weiter unten.

Syntax

ignore_user_abort(?bool $enable = null): int
  • $enable — übergeben Sie true, um Client-Trennungen zu ignorieren, oder false, um den Standard wiederherzustellen (Abbruch bei Trennung). Wenn Sie das Argument weglassen, bleibt die aktuelle Einstellung unverändert und wird nur zurückgegeben.
  • Rückgabewert — die vorherige Einstellung als Integer (1 = Abbrüche wurden ignoriert, 0 = wurden nicht ignoriert). Damit können Sie den Zustand speichern und wiederherstellen.
<?php
$previous = ignore_user_abort(true);   // turn it on, remember old value
// ... critical work ...
ignore_user_abort($previous);          // restore whatever it was before

Dieselbe Einstellung kann global in php.ini mit der ignore_user_abort-Direktive konfiguriert werden; der Aufruf der Funktion überschreibt sie für die aktuelle Anfrage.

Grundlegende Verwendung

Rufen Sie die Funktion einmal am Anfang der zu schützenden Arbeit auf:

<?php
// Keep running even if the user disconnects.
ignore_user_abort(true);

// Critical code that must not be interrupted.
saveOrderToDatabase();
chargePayment();
sendConfirmationEmail();

// Optional: go back to the default behaviour.
ignore_user_abort(false);

Beachten Sie, dass ignore_user_abort() das Skript am Leben hält, aber PHPs max_execution_time-Limit nicht aufhebt. Eine lang laufende Aufgabe kann dennoch durch das Zeitlimit beendet werden — kombinieren Sie es daher bei Bedarf mit set_time_limit().

Den Abbruch mit connection_aborted() erkennen

Ein Abbruch zu ignorieren bedeutet nicht, dass Sie nicht darauf reagieren können. Die Funktion connection_aborted() gibt 1 zurück, sobald der Client die Verbindung getrennt hat, und 0 andernfalls. Sie können sie innerhalb einer Schleife prüfen und entscheiden, ob Sie weitermachen, aufräumen oder beenden möchten.

Eine Besonderheit: PHP aktualisiert den Verbindungsstatus nur dann, wenn es versucht, Ausgabe zu senden und der Puffer geleert wird. Um einen Abbruch mitten in einer Schleife zu erkennen, verwendet man daher typischerweise echo in Verbindung mit flush(), was PHP zwingt, den geschlossenen Socket zu bemerken.

<?php
ignore_user_abort(true);

for ($i = 0; $i < 10; $i++) {
    // Push some output so PHP checks the connection state.
    echo "Step $i\n";
    flush();

    // connection_aborted() returns 1 after the client disconnects.
    if (connection_aborted()) {
        // The user left — stop early and clean up if we want to.
        break;
    }

    doExpensiveStep($i);
}

ignore_user_abort(false);

Hier ermöglicht connection_aborted() dem Skript, selbst zu entscheiden: Es kann still zu Ende laufen, protokollieren, dass der Benutzer gegangen ist, oder frühzeitig abbrechen. Verwandt: connection_status() meldet alle drei Zustände (normal, abgebrochen, abgelaufen) als Bitmaske.

Ein praktisches Beispiel für Hintergrundaufgaben

Ein häufiges Muster ist es, die Antwort zu senden, die Verbindung zu schließen, damit der Browser nicht mehr wartet, und dann im Hintergrund schwere Arbeit fortzusetzen. ignore_user_abort(true) macht den „Fortsetzen"-Teil möglich.

<?php
// 1. Keep running after the browser is released.
ignore_user_abort(true);
set_time_limit(0); // no execution-time cap for the background work

// 2. Send the response and flush the output buffers.
ob_start();
echo "Thanks! Your request is being processed.";
$size = ob_get_length();
header("Content-Length: $size");
header("Connection: close");
ob_end_flush();
flush();

if (function_exists('fastcgi_finish_request')) {
    fastcgi_finish_request(); // PHP-FPM: detach from the client now
}

// 3. The user's browser is already done. This runs regardless.
processLargeReport();

Der Browser erhält eine schnelle Antwort und hört auf zu laden, während der Server die langsame Aufgabe abschließt. Ohne ignore_user_abort(true) würde diese Hintergrundarbeit in dem Moment beendet, in dem PHP die geschlossene Verbindung bemerkt.

Warum der Abbruch spät erkannt wird

PHP puffert Ausgaben. Solange dieser Puffer nicht an den Client geleert wird, hat PHP keinen Grund, den Socket anzufassen, und erfährt daher nie, dass er geschlossen ist. Deshalb können Skripte, die keine Ausgabe erzeugen (oder deren Ausgabe gepuffert bleibt), nach einer Trennung bis zum Ende laufen, ohne jemals connection_aborted() === 1 zu melden. Wenn Sie eine zeitnahe Abbrucherkennung benötigen, senden Sie periodisch einen kleinen Heartbeat und leeren Sie ihn mit flush(), wie in der obigen Schleife. Ausgabepuffer-Hilfsfunktionen wie ob_flush() und ob_end_flush() geben Ihnen feinere Kontrolle darüber, wann Daten den Puffer verlassen.

Häufige Fallstricke

  • Es überschreibt das Zeitlimit nicht. Verwenden Sie set_time_limit(0) (oder einen großzügigen Wert) zusammen damit für lange Aufgaben.
  • Erkennung erfordert Ausgabe + Flush. connection_aborted() wird nicht auf 1 wechseln, wenn Ihr Skript nie etwas an den Client schreibt.
  • Ein unkontrolliertes Skript ist schwerer zu stoppen. Mit ignorierten Abbrüchen verbraucht eine fehlerhafte Endlosschleife weiterhin Ressourcen, weil der Benutzer sie nicht mehr abbrechen kann. Kombinieren Sie die Funktion immer mit sinnvollen Grenzen.
  • CLI-Skripte sind nicht betroffen. Auf der Kommandozeile gibt es keine Client-Verbindung, daher ist die Funktion dort wirkungslos — verwenden Sie sie in Web-(Anfrage-)Kontexten.

Fazit

ignore_user_abort() hält ein PHP-Skript am Laufen, nachdem der Client die Verbindung getrennt hat, was für die sichere Durchführung kritischer oder im Hintergrund laufender Arbeit unerlässlich ist. Kombinieren Sie es mit connection_aborted() zur Erkennung von Trennungen, flush() um diese Erkennung zu erzwingen, und set_time_limit() um zu vermeiden, mitten in einer Aufgabe unterbrochen zu werden — und Sie haben ein zuverlässiges Muster für Arbeit, die nicht halb abgeschlossen hinterlassen werden darf.

Practice

Übung
Was macht die Funktion ignore_user_abort() in PHP?
Was macht die Funktion ignore_user_abort() in PHP?
Was this page helpful?