Error and Exception Handling in PHP
try / catch / finally, custom exceptions and native errors from PHP 8
🎯 Live Demo
Result of dividirSeguro():
Try different values
📖 Code Explanation
Complete code
class NumeroInvalidoException extends Exception {}
function dividirSeguro(float $dividendo, float $divisor): float {
if ($divisor < 0) {
throw new NumeroInvalidoException(t('El divisor no puede ser negativo') . " (\$divisor).");
}
return $dividendo / $divisor; // PHP 8 lanza DivisionByZeroError si \$divisor es 0}
try {
$resultado = dividirSeguro($dividendo, $divisor);
echo t('Resultado:') . " \$resultado";
} catch (DivisionByZeroError $e) {
echo t('No se puede dividir por cero:') . " " . \$e->getMessage();
} catch (NumeroInvalidoException $e) {
echo t('Dato inválido:') . " " . \$e->getMessage();
} catch (Throwable $e) {
echo t('Error inesperado:') . " " . \$e->getMessage();
} finally {
echo t('Esto se ejecuta siempre.');
}
📝 Custom exception
What does it do? NumeroInvalidoException extends Exception creates your own error type, with a descriptive name, which you can catch independently from the rest.
📝 Order of the catch
Why does it matter? PHP evaluates the catch blocks in order and uses the first one that matches the thrown type.. That's why the more specific ones (DivisionByZeroError, NumeroInvalidoException) go before the generic Throwable.
💡 Concept: Error vs Exception
Since PHP 7, fatal errors (like DivisionByZeroError) are also catchable objects.. Throwable is the interface common to Error and Exception, so a catch (Throwable $e) catches anything that slips past the previous ones.
📝 The block finally
What does it do? It always runs, whether there was an exception or not. Ideal for releasing resources (closing a connection, a file, etc.).
🎯 Key Concepts
try / catch / finally
try: code that might failcatch: what to do if it failsfinally: always runs
Custom exceptions
extends Exception- Give the error a name and context
Throwable
- Common interface of
ErrorandException - Final safety net in the catch
💪 Practical Exercise
Extend error handling
- Create an exception
NumeroDemasiadoGrandeExceptionthat is thrown if the dividend exceeds 1.000.000. - Add a method
getMensajeUsuario()toNumeroInvalidoExceptionthat returns a friendly message different from the technical one. - Register a global
set_exception_handler()that shows a generic error page for any uncaught exception.
Solution 1
class NumeroDemasiadoGrandeException extends Exception {}
if ($dividendo > 1000000) {
throw new NumeroDemasiadoGrandeException(t('Dividendo demasiado grande:') . " $dividendo");
}
Solution 2
class NumeroInvalidoException extends Exception {
public function getMensajeUsuario(): string {
return t('Revisa los números introducidos, hay algo incorrecto.');
}
}
Solution 3
set_exception_handler(function (Throwable $e) {
error_log($e->getMessage());
echo t('Ha ocurrido un error inesperado. Inténtalo más tarde.');
});