Instead of relying on error return codes, modern PHP uses exceptions to signal and handle error conditions.
function divide(float $a, float $b): float
{
if ($b === 0.0) {
throw new InvalidArgumentException('Cannot divide by zero.');
}
return $a / $b;
}
try {
echo divide(10, 0);
} catch (InvalidArgumentException $e) {
echo 'Error: ' . $e->getMessage();
} finally {
echo 'Calculation attempted.'; // always runs, whether an exception occurred or not
}
You can catch multiple exception types in one block using |:
try {
// risky code
} catch (InvalidArgumentException | TypeError $e) {
// handle either
}
PHP's built-in exception hierarchy includes Exception and Error (both implement Throwable), with useful subclasses like InvalidArgumentException, RuntimeException, OutOfRangeException, DivisionByZeroError, and TypeError. Since PHP 8.0, unhandled Throwables produce a clear stack trace by default, making debugging much easier than older PHP versions.
Since PHP 8.0, you can also omit the caught variable entirely if you don't need it: catch (RuntimeException) { ... }.