preg_last_error()
Scopri come preg_last_error() di PHP restituisce il codice di errore dell'ultima chiamata PCRE, con costanti, preg_last_error_msg() ed esempi.
Introduzione
Le espressioni regolari sono uno strumento potente per manipolare e cercare stringhe in PHP. A volte le operazioni con le regex falliscono a causa di pattern non validi o limiti del motore. La funzione preg_last_error() aiuta a identificare questi fallimenti restituendo il codice di errore dell'ultima chiamata alla funzione PCRE.
Sintassi
preg_last_error(): intLa funzione non accetta argomenti. Restituisce una costante intera che descrive cosa è andato storto durante l'ultima chiamata a una funzione PCRE — come preg_match(), preg_match_all(), preg_replace() o preg_split(). Se l'ultima chiamata è riuscita, restituisce PREG_NO_ERROR (0).
Perché è necessaria
Le funzioni PCRE sono particolari: quando falliscono, non lanciano un'eccezione. Invece, preg_match() restituisce false (non 0 — quello significa "nessuna corrispondenza") e preg_replace() restituisce null. Questi valori di ritorno indicano che qualcosa è fallito, ma non perché. preg_last_error() colma questa lacuna riportando il motivo sottostante.
Ecco perché bisogna confrontare con === anziché con un == non rigoroso: 0 (nessuna corrispondenza) e false (errore) appaiono entrambi come "falsy", ma significano cose molto diverse.
Costanti di errore
preg_last_error() restituisce una delle seguenti costanti intere. I valori numerici sono mostrati a titolo di riferimento, ma è sempre consigliabile confrontare con la costante nominale.
| Costante | Valore | Significato |
|---|---|---|
PREG_NO_ERROR | 0 | Nessun errore — l'ultima operazione è riuscita. |
PREG_INTERNAL_ERROR | 1 | Errore interno PCRE (spesso un pattern malformato). |
PREG_BACKTRACK_LIMIT_ERROR | 2 | Il pattern ha raggiunto il limite pcre.backtrack_limit. |
PREG_RECURSION_LIMIT_ERROR | 3 | Il pattern ha raggiunto il limite pcre.recursion_limit. |
PREG_BAD_UTF8_ERROR | 4 | Il soggetto non è UTF-8 valido (con il modificatore u). |
PREG_BAD_UTF8_OFFSET_ERROR | 5 | L'offset non corrispondeva all'inizio di un code point UTF-8 valido. |
PREG_JIT_STACKLIMIT_ERROR | 6 | Il pattern ha esaurito il limite dello stack JIT. |
Da PHP 8.0, preg_last_error_msg() restituisce le stesse informazioni come stringa leggibile dall'uomo, molto utile per il logging.
Generare e leggere un errore
Un fallimento comune nel mondo reale è il backtracking catastrofico, in cui un pattern scritto male costringe il motore a provare un numero enorme di percorsi e supera il limite di backtrack. L'esempio seguente abbassa pcre.backtrack_limit per rendere il fallimento riproducibile, poi esamina il risultato.
<?php
// Lower the limit so the failure is easy to reproduce.
ini_set('pcre.backtrack_limit', '100');
$pattern = '/(\w+)*$/'; // nested quantifier — backtracks heavily
$string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa!';
$result = preg_match($pattern, $string, $matches);
if ($result === false) {
echo 'preg_match() failed!' . PHP_EOL;
echo 'Error code: ' . preg_last_error() . PHP_EOL;
echo 'Error message: ' . preg_last_error_msg() . PHP_EOL;
if (preg_last_error() === PREG_BACKTRACK_LIMIT_ERROR) {
echo 'The pattern was too expensive to evaluate.' . PHP_EOL;
}
} elseif ($result === 1) {
echo 'Match found.' . PHP_EOL;
} else {
echo 'No match.' . PHP_EOL;
}Output:
preg_match() failed!
Error code: 2
Error message: Backtrack limit exhausted
The pattern was too expensive to evaluate.Il codice di errore 2 corrisponde a PREG_BACKTRACK_LIMIT_ERROR. È fondamentale che il controllo if ($result === false) sia ciò che ci indica che si è verificato un errore reale — uno 0 qui significherebbe semplicemente che il pattern non ha trovato corrispondenze.
Rilevare input UTF-8 non valido
Quando si usa il modificatore u (unicode) su una stringa che non è UTF-8 valido, PCRE interrompe l'esecuzione e imposta PREG_BAD_UTF8_ERROR:
<?php
$result = preg_match('/./u', "\x80"); // \x80 is not a valid UTF-8 sequence
if ($result === false && preg_last_error() === PREG_BAD_UTF8_ERROR) {
echo 'Invalid UTF-8 input: ' . preg_last_error_msg();
}
// Invalid UTF-8 input: Malformed UTF-8 characters, possibly incorrectly encodedQuesta è una fonte frequente di bug silenziosi quando si elaborano dati inviati dall'utente, quindi è buona pratica proteggersi da essa.
Errori comuni
- Controllare immediatamente.
preg_last_error()riflette solo la chiamata PCRE più recente. Qualsiasi chiamata successiva alla regex sovrascrive il valore, quindi è necessario leggerlo subito dopo l'operazione di interesse. falsevs0. Usare sempre===.preg_match()restituisce0per "nessuna corrispondenza" efalseper un errore — non sono intercambiabili.- Fallimenti di
preg_replace(). Quandopreg_replace()restituiscenull, vale anche la pena chiamarepreg_last_error()per capirne il motivo.
Conclusione
preg_last_error() trasforma un false opaco in un motivo concreto, rendendola indispensabile per il debug delle espressioni regolari in PHP. Confrontando i valori di ritorno con === e ispezionando il codice di errore (o preg_last_error_msg()), è possibile distinguere chiaramente i fallimenti del motore dalle semplici assenze di corrispondenza. Per le funzioni i cui fallimenti segnala, vedere preg_match(), preg_replace() e preg_split().