Manchmal muss ein PHP-Script bewusst eine Pause einlegen. Das kann nötig sein, um die Anfragerate an eine externe API zu begrenzen, um nach einem fehlgeschlagenen Versuch eine Wartezeit einzuhalten oder um in einem CLI-Script einen Countdown umzusetzen. PHP stellt dafür die Funktionen sleep() und usleep() bereit.
sleep() für Pausen in ganzen Sekunden
Die Funktion sleep() erwartet einen ganzzahligen Parameter und pausiert die Script-Ausführung für die angegebene Anzahl an Sekunden. Während der Pause verbraucht das Script keine CPU-Zeit.
<?php
echo 'Start: ' . date('H:i:s');
sleep(3);
echo ' Ende: ' . date('H:i:s');
/* Ausgabe z.B.: Start: 14:05:10 Ende: 14:05:13 */
?>
Der Rückgabewert ist 0 bei Erfolg. Falls die Pause durch ein Signal unterbrochen wird, gibt sleep() die Anzahl der verbleibenden Sekunden zurück.
usleep() für Pausen unter einer Sekunde
Wenn eine Verzögerung kürzer als eine Sekunde sein soll, kommt usleep() zum Einsatz. Der Parameter wird in Mikrosekunden angegeben. Eine Mikrosekunde ist ein Millionstel einer Sekunde.
<?php
/* 500 Millisekunden warten (= 0,5 Sekunden) */
usleep(500000);
/* 100 Millisekunden warten (= 0,1 Sekunden) */
usleep(100000);
/* 1,5 Sekunden warten (Kombination) */
sleep(1);
usleep(500000);
?>
Da der Wert in Mikrosekunden angegeben wird, muss für eine halbe Sekunde der Wert 500000 übergeben werden (500 * 1000). Für bessere Lesbarkeit kann man die Berechnung direkt im Code schreiben: usleep(500 * 1000).
Praxisbeispiel: API-Anfragen drosseln
Viele externe APIs begrenzen die Anzahl der erlaubten Anfragen pro Sekunde. Wer in einer Schleife mehrere Anfragen nacheinander abschickt, muss zwischen den Aufrufen eine Pause einlegen, um nicht gesperrt zu werden.
<?php
$ids = [101, 102, 103, 104, 105];
foreach ($ids as $id) {
$daten = file_get_contents(
'https://api.example.com/produkt/' . $id
);
echo 'Produkt ' . $id . ' geladen.' . PHP_EOL;
/* 200ms Pause zwischen den Anfragen */
usleep(200 * 1000);
}
?>
Ohne die Pause würden alle Anfragen nahezu gleichzeitig abgeschickt. Mit usleep(200 * 1000) werden maximal fünf Anfragen pro Sekunde gesendet.
Praxisbeispiel: Wiederholung bei Fehler (Retry)
Bei vorübergehenden Fehlern wie einem Netzwerk-Timeout ist es sinnvoll, den Versuch nach einer kurzen Wartezeit zu wiederholen. Dabei verdoppelt sich die Wartezeit mit jedem Versuch, um den Zielserver nicht zusätzlich zu belasten.
<?php
function apiAufrufMitRetry(string $url, int $maxVersuche = 3): string|false
{
for ($versuch = 1; $versuch <= $maxVersuche; $versuch++) {
$ergebnis = @file_get_contents($url);
if ($ergebnis !== false) {
return $ergebnis;
}
if ($versuch < $maxVersuche) {
$wartezeit = pow(2, $versuch);
echo 'Versuch ' . $versuch
. ' fehlgeschlagen. Warte '
. $wartezeit . 's ...' . PHP_EOL;
sleep($wartezeit);
}
}
return false;
}
?>
Beim ersten Fehlschlag wartet das Script 2 Sekunden, beim zweiten 4 Sekunden. Dieses Muster wird als Exponential Backoff bezeichnet und ist ein bewährtes Verfahren bei der Kommunikation mit externen Diensten.
Wichtig: max_execution_time beachten
Jedes PHP-Script hat eine maximale Laufzeit, die in der Konfiguration unter max_execution_time festgelegt ist (Standard: 30 Sekunden). Die durch sleep() verbrachte Zeit zählt auf den meisten Systemen nicht zur Laufzeit dazu, auf Windows-Systemen allerdings schon.
<?php
/* Laufzeitlimit fuer langes Script erhoehen */
set_time_limit(120);
/* Oder: Kein Zeitlimit setzen (Vorsicht!) */
set_time_limit(0);
?>
Bei Scripts, die länger laufen sollen, empfiehlt es sich, die Laufzeit mit set_time_limit() gezielt zu erhöhen statt sie komplett abzuschalten.
sleep() im Web-Kontext vermeiden
In einem normalen Web-Request blockiert sleep() die gesamte Antwort. Der Besucher sieht so lange eine weiße Seite, bis das Script fertig ist. Das sollte nach Möglichkeit vermieden werden. Im Browser erscheinen Ausgaben erst, wenn das Script komplett durchgelaufen ist, weil PHP die Antwort standardmäßig puffert.
Für Aufgaben, die längere Pausen erfordern (etwa Massen-E-Mail-Versand oder Datenimporte), sollte man stattdessen einen Cronjob oder einen Hintergrund-Worker verwenden. Die sleep()-Funktion eignet sich dagegen gut für CLI-Scripts, die direkt auf dem Server ausgeführt werden.
time_nanosleep() für präzise Pausen
Wer noch feinere Kontrolle über die Wartezeit benötigt, kann time_nanosleep() verwenden. Die Funktion erwartet zwei Parameter: Sekunden und Nanosekunden.
<?php
/* 1,5 Sekunden warten */
time_nanosleep(1, 500000000);
/* 0,25 Sekunden warten */
time_nanosleep(0, 250000000);
?>
In der Praxis reicht usleep() für die allermeisten Fälle aus. time_nanosleep() ist vor allem dann relevant, wenn die Wartezeit exakt in Sekunden und Bruchteilen angegeben werden soll, ohne selbst umrechnen zu müssen.