©Sergey Emelyanov 2025 | Alle Rechte vorbehalten
In Go gibt es das Schlüsselwort defer, mit dem sich die Ausführung einer Funktion auf den Moment nach dem Return der aktuellen Funktion verschieben lässt. Ein typisches Beispiel in Go sieht so aus:
func main() {
defer fmt.Println("world!")
fmt.Print("Hello ")
}
Das Programm gibt „Hello world!“ aus, weil der deferred Aufruf von fmt.Println erst nach Beendigung der Main-Funktion erfolgt.
In PHP gibt es – anders als in Go – kein eingebautes defer. Jedoch lässt sich ein ähnlicher Effekt erzielen, indem man ein Objekt erzeugt, dessen Destruktor den "verzögerten" Code ausführt. So könnte man in PHP folgenden Ansatz wählen:
$defer = new class {
public function __destruct()
{
echo 'world!', PHP_EOL;
}
};
echo 'Hello ';
Beim Verlassen des Gültigkeitsbereichs und dem Freigeben des Objekts wird automatisch der Destruktor aufgerufen, der „world!“ ausgibt.
Doch dieses Konstrukt ist nicht allzu elegant, und oft benötigt man mehrere deferred Aufgaben in einem Skript.
Um dieses Problem zu lösen, gibt es die Bibliothek php-defer/php-defer (https://github.com/php-defer/php-defer). Diese Bibliothek stellt eine Funktion bereit, mit der man Closures als deferred ausführen kann – ähnlich wie in Node.js. Ein Beispiel:
use function Illuminate\Support\defer;
defer($_, static function (): void {
echo 'rld!', PHP_EOL;
});
defer($_, static function (): void {
echo ', wo';
});
echo 'Hello';
Bei Ausführung wird der Code so angeordnet, dass der HTTP-Response (bzw. das Ende des Skripts) zuerst ausgegeben wird („Hello“), und danach die deferred Aufgaben ablaufen, sodass das Endergebnis beispielsweise „Hello, world!“ ergibt.
Ein naheliegender Vergleich stellt sich mit dem finally-Block in PHP. Doch der Vorteil von defer liegt in der Flexibilität:
Auch Laravel hat den Nutzen von defer erkannt. In Laravel gibt es die Funktion Illuminate\Support\defer, mit der du Deferred Functions in deinen Anwendungen einsetzen kannst. Zum Beispiel im Kontext eines CRM-Deal-Managements:
<?php
namespace App\Services;
use App\Models\Deal;
use Illuminate\Support\Facades\Log;
use function Illuminate\Support\defer;
class DealService
{
/**
* Erstellt einen neuen Deal und veranlasst nach der HTTP-Antwort weitere Hintergrundaufgaben.
*
* @param array $data
* @return \App\Models\Deal
*/
public function createDeal(array $data): Deal
{
// Erstellen des Deals in der Datenbank
$deal = Deal::create($data);
// Mit defer wird eine Closure registriert, die nach dem Versand der Response ausgeführt wird.
defer(fn() => $this->processDealMetrics($deal));
return $deal;
}
/**
* Führt komplexe Aufgaben aus, die mit dem neu erstellten Deal zusammenhängen.
*
* @param \App\Models\Deal $deal
* @return void
*/
protected function processDealMetrics(Deal $deal): void
{
Log::info("Deferred: Verarbeitung der Kennzahlen für Deal mit ID {$deal->id} beginnt.");
// Hier könnten aufwendige Berechnungen, API-Aufrufe oder Benachrichtigungen erfolgen...
Log::info("Deferred: Kennzahlen für Deal mit ID {$deal->id} wurden erfolgreich verarbeitet.");
}
}
In diesem Beispiel erstellt der DealService einen neuen Deal und verwendet unmittelbar danach defer, um die Funktion processDealMetrics asynchron abarbeiten zu lassen – und das, nachdem der HTTP-Response bereits an den Client gesendet wurde. Somit bleibt die Anwendung reaktionsschnell, während Hintergrundprozesse parallel abgearbeitet werden.
Einziger Nachteil:
Der Ansatz mit php-defer bzw. Illuminate\Support\defer ist bislang in erster Linie innerhalb des Frameworks sinnvoll einsetzbar. Außerhalb von Laravel musst du auf eigene Implementierungen (wie das oben gezeigte Destruktor-Muster) zurückgreifen.
Fazit
defer in PHP ermöglicht es, Aufgaben zu verschieben, die erst nach Beendigung des Hauptscriptausführungsflusses ausgeführt werden sollen. Inspiriert vom defer-Schlüsselwort in Go, können wir in PHP mithilfe von Destruktoren oder Bibliotheken wie php-defer ähnliche Funktionalitäten erzielen. Laravel hat dieses Prinzip in seine Funktion Illuminate\Support\defer integriert, die in vielen Anwendungen – zum Beispiel im CRM-Bereich bei der Verwaltung von Deals – die Codebasis sauberer und reaktionsfähiger macht, indem nachträgliche Prozesse asynchron abgearbeitet werden. Dieser Ansatz verbessert nicht nur die Performance, sondern erhöht auch die Übersichtlichkeit deines Codes, da du Aufgaben genau an der Stelle deklarieren kannst, an der sie benötigt werden, ohne die komplette Struktur umzustellen.
©Sergey Emelyanov 2025 | Alle Rechte vorbehalten