Signatur
Beschreibung
preg_last_error() liefert einen ganzzahligen Fehlercode, der den Status der zuletzt durchgeführten PCRE-Regulärausdrucks-Operation beschreibt. Da PCRE-Funktionen wie preg_match() oder preg_replace() bei internen Fehlern häufig false oder null zurückgeben, ohne den genauen Grund zu nennen, ermöglicht diese Funktion eine präzise Fehlerdiagnose.
Die zurückgegebenen Fehlercodes entsprechen vordefinierten Konstanten: PREG_NO_ERROR (0) bedeutet keinen Fehler, PREG_INTERNAL_ERROR (1) zeigt einen internen PCRE-Fehler an, PREG_BACKTRACK_LIMIT_ERROR (2) und PREG_RECURSION_LIMIT_ERROR (3) weisen auf überschrittene Limits aus der php.ini (pcre.backtrack_limit bzw. pcre.recursion_limit) hin. PREG_BAD_UTF8_ERROR (4) und PREG_BAD_UTF8_OFFSET_ERROR (5) signalisieren Probleme mit ungültigem UTF-8-Input.
Ab PHP 8.0 empfiehlt sich alternativ preg_last_error_msg(), die eine lesbare Fehlermeldung als String liefert. In älteren PHP-Versionen ist preg_last_error() jedoch die einzige Möglichkeit, detaillierte PCRE-Fehlerinformationen abzurufen.
Typischer Einsatz: nach jedem kritischen preg_match()- oder preg_replace()-Aufruf prüfen, ob das Ergebnis false ist, und dann preg_last_error() auswerten, um den Fehlergrund zu ermitteln und gegebenenfalls Limits anzupassen oder den Input zu validieren.
Rückgabewert
PREG_NO_ERROR (0) bei Erfolg, PREG_INTERNAL_ERROR (1), PREG_BACKTRACK_LIMIT_ERROR (2), PREG_RECURSION_LIMIT_ERROR (3), PREG_BAD_UTF8_ERROR (4), PREG_BAD_UTF8_OFFSET_ERROR (5) oder PREG_JIT_STACKLIMIT_ERROR (6, ab PHP 7.0).Beispiele
Backtrack-Limit-Fehler erkennen
<?php
// Ein Muster, das exzessives Backtracking erzeugt
$pattern = '/(?:a+)+$/';
$subject = str_repeat('a', 50) . 'b';
$result = preg_match($pattern, $subject);
if ($result === false) {
$errorCode = preg_last_error();
switch ($errorCode) {
case PREG_BACKTRACK_LIMIT_ERROR:
echo 'Fehler: Backtrack-Limit überschritten (pcre.backtrack_limit).' . PHP_EOL;
break;
case PREG_RECURSION_LIMIT_ERROR:
echo 'Fehler: Rekursions-Limit überschritten (pcre.recursion_limit).' . PHP_EOL;
break;
case PREG_INTERNAL_ERROR:
echo 'Fehler: Interner PCRE-Fehler.' . PHP_EOL;
break;
default:
echo 'Unbekannter PCRE-Fehler: ' . $errorCode . PHP_EOL;
}
} else {
echo 'Treffer gefunden: ' . ($result ? 'Ja' : 'Nein') . PHP_EOL;
}
Hilfsfunktion zur lesbaren Fehlerausgabe
<?php
function pcreErrorName(int $code): string {
$errors = [
PREG_NO_ERROR => 'PREG_NO_ERROR',
PREG_INTERNAL_ERROR => 'PREG_INTERNAL_ERROR',
PREG_BACKTRACK_LIMIT_ERROR => 'PREG_BACKTRACK_LIMIT_ERROR',
PREG_RECURSION_LIMIT_ERROR => 'PREG_RECURSION_LIMIT_ERROR',
PREG_BAD_UTF8_ERROR => 'PREG_BAD_UTF8_ERROR',
PREG_BAD_UTF8_OFFSET_ERROR => 'PREG_BAD_UTF8_OFFSET_ERROR',
];
return $errors[$code] ?? 'UNBEKANNT (' . $code . ')';
}
// UTF-8-Fehler provozieren
$invalidUtf8 = "\xc3\x28"; // ungültige UTF-8-Sequenz
$result = preg_match('/./u', $invalidUtf8);
if ($result === false) {
echo 'PCRE-Fehler: ' . pcreErrorName(preg_last_error()) . PHP_EOL;
} else {
echo 'Kein Fehler, Ergebnis: ' . $result . PHP_EOL;
}
// Wichtig · Fallstricke
PHP 8.0+: Seit PHP 8.0 steht preg_last_error_msg() zur Verfügung, die direkt eine lesbare Fehlermeldung als String zurückgibt und preg_last_error() in den meisten Fällen ersetzt.
Limits anpassen: Bei PREG_BACKTRACK_LIMIT_ERROR kann ini_set('pcre.backtrack_limit', 10000000) helfen, jedoch ist es besser, das Regex-Muster zu optimieren (z. B. durch atomare Gruppen oder besitzgreifende Quantoren), um katastrophales Backtracking zu vermeiden.
Fehlercode bleibt gespeichert: Der Fehlercode wird pro Request gesetzt und bleibt bis zum nächsten PCRE-Aufruf erhalten. Immer direkt nach dem verdächtigen Aufruf prüfen, nicht erst später im Code.