W3docs

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(): int

La 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.

CostanteValoreSignificato
PREG_NO_ERROR0Nessun errore — l'ultima operazione è riuscita.
PREG_INTERNAL_ERROR1Errore interno PCRE (spesso un pattern malformato).
PREG_BACKTRACK_LIMIT_ERROR2Il pattern ha raggiunto il limite pcre.backtrack_limit.
PREG_RECURSION_LIMIT_ERROR3Il pattern ha raggiunto il limite pcre.recursion_limit.
PREG_BAD_UTF8_ERROR4Il soggetto non è UTF-8 valido (con il modificatore u).
PREG_BAD_UTF8_OFFSET_ERROR5L'offset non corrispondeva all'inizio di un code point UTF-8 valido.
PREG_JIT_STACKLIMIT_ERROR6Il 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 encoded

Questa è 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.
  • false vs 0. Usare sempre ===. preg_match() restituisce 0 per "nessuna corrispondenza" e false per un errore — non sono intercambiabili.
  • Fallimenti di preg_replace(). Quando preg_replace() restituisce null, vale anche la pena chiamare preg_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().

Esercizio

Pratica
Cosa fa la funzione 'preg_last_error' in PHP?
Cosa fa la funzione 'preg_last_error' in PHP?
Was this page helpful?