W3docs

catch

Scopri come usare il costrutto "try...catch" in PHP per gestire errori ed eccezioni nel codice in modo efficace e sicuro.

La parola chiave catch in PHP

Quando il codice all'interno di un blocco try incontra un'eccezione — un object che segnala che qualcosa è andato storto — l'esecuzione si interrompe e PHP cerca un blocco catch corrispondente per gestirla. La parola chiave catch indica il tipo di eccezione che può gestire e assegna l'object lanciato a una variabile così da poterlo esaminare. Senza un catch, un'eccezione non gestita diventa un errore fatale e interrompe lo script.

Questa pagina illustra la sintassi di catch, come PHP sceglie quale blocco eseguire, come leggere i dettagli dall'eccezione catturata e i pattern comuni (catch multipli, tipi union, rilancio) che utilizzerai nel codice reale.

Sintassi

Un blocco catch segue sempre un blocco try. Dichiara un tipo di eccezione e una variabile che riceve l'object lanciato:

<?php

try {
    // Code that may throw an exception
} catch (Exception $e) {
    // Runs only if a matching exception is thrown above
    echo $e->getMessage();
}

PHP abbina un blocco catch quando l'object lanciato è un'istanza del tipo dichiarato. Poiché ogni eccezione built-in estende la classe base Exception (ed entrambe estendono l'interfaccia Throwable), catch (Exception $e) intercetta la maggior parte delle eccezioni. Catturare Throwable permette inoltre di gestire gli object Error come TypeError e DivisionByZeroError.

Puoi abbinare catch a un blocco finally per eseguire codice di pulizia indipendentemente dal fatto che si sia verificata un'eccezione.

Un esempio funzionante

La funzione seguente lancia un'eccezione quando le si chiede di dividere per zero. Il blocco catch intercetta quell'eccezione e la segnala invece di far crashare lo script:

<?php

function divide($numerator, $denominator)
{
    if ($denominator == 0) {
        throw new InvalidArgumentException("Division by zero.");
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage();
}

// Output: Error: Division by zero.

Nota che lo script continua l'esecuzione dopo il catch — il controllo riprende dalla riga successiva alla struttura try/catch invece di interrompersi.

Leggere i dettagli dall'eccezione catturata

La variabile in una clausola catch ($e nell'esempio) è l'object exception stesso. Espone metodi che descrivono cosa è accaduto:

<?php

try {
    throw new RuntimeException("Disk is full", 28);
} catch (RuntimeException $e) {
    echo $e->getMessage();  // Disk is full
    echo "\n";
    echo $e->getCode();     // 28
    echo "\n";
    echo $e->getLine();     // 4  (line where it was thrown)
}
MetodoRestituisce
getMessage()Il messaggio di errore leggibile
getCode()Il codice di errore intero passato al costruttore
getFile()Il file in cui l'eccezione è stata creata
getLine()Il numero di riga in cui è stata lanciata
getTrace()Lo stack trace come array
getPrevious()L'eccezione precedente (per eccezioni concatenate)

Catturare più tipi di eccezione

Quando un blocco try può fallire in modi diversi, elenca più blocchi catch. PHP li prova dall'alto verso il basso ed esegue il primo che corrisponde, quindi ordina i tipi più specifici prima di quelli generali:

<?php

try {
    // Code that may throw different exceptions
    throw new InvalidArgumentException("bad input");
} catch (InvalidArgumentException $e) {
    echo "Invalid argument: " . $e->getMessage();
} catch (RuntimeException $e) {
    echo "Runtime problem: " . $e->getMessage();
} catch (Exception $e) {
    echo "Something else: " . $e->getMessage();
}

// Output: Invalid argument: bad input

Se catch (Exception $e) venisse per primo, ingloberebbe tutto e i blocchi più specifici sottostanti non verrebbero mai eseguiti.

Union catch (PHP 7.1+)

Quando due tipi di eccezione diversi richiedono la stessa gestione, combinali con un pipe | invece di duplicare il blocco:

<?php

try {
    throw new RuntimeException("connection reset");
} catch (InvalidArgumentException | RuntimeException $e) {
    echo "Handled: " . $e->getMessage();
}

// Output: Handled: connection reset

Catch non-capturing (PHP 8.0+)

Se non hai bisogno dell'object eccezione, puoi omettere completamente la variabile:

<?php

try {
    throw new Exception("ignored details");
} catch (Exception) {
    echo "An error occurred, retrying...";
}

// Output: An error occurred, retrying...

Rilancio ed eccezioni concatenate

A volte un blocco catch dovrebbe registrare il problema e poi propagarlo — oppure avvolgere un'eccezione di basso livello in una più significativa. Passa l'originale come terzo argomento del costruttore per preservare la catena:

<?php

try {
    try {
        throw new RuntimeException("low-level failure");
    } catch (RuntimeException $e) {
        // Wrap and re-throw with context preserved
        throw new Exception("High-level operation failed", 0, $e);
    }
} catch (Exception $e) {
    echo $e->getMessage();              // High-level operation failed
    echo "\n";
    echo $e->getPrevious()->getMessage(); // low-level failure
}

Best practice

  • Cattura il tipo più specifico che riesci a gestire. Un generico catch (Throwable $e) può nascondere bug assorbendo errori di programmazione che avresti dovuto correggere.
  • Ordina dal più specifico al più generale. Le sottoclassi specifiche devono precedere i tipi padre.
  • Non lasciare un catch vuoto. Scartare silenziosamente un'eccezione rende i fallimenti invisibili; almeno registrala.
  • Lancia eccezioni, non flag di errore. Combina catch con throw così i chiamanti non possono ignorare accidentalmente i fallimenti.
  • Usa finally per la pulizia (chiusura di file, rilascio di lock) che deve avvenire sia nel percorso di successo che in quello di fallimento.

Argomenti correlati

Pratica

Pratica
Cosa succede quando un'eccezione viene lanciata e non catturata in PHP?
Cosa succede quando un'eccezione viene lanciata e non catturata in PHP?
Was this page helpful?