How do you handle errors and exceptions in PHP 8, and what changed from earlier versions?
PHP historically had two parallel systems — traditional errors and exceptions — and PHP 7 unified them. Most fatal errors now throw Error, and both Error and Exception implement Throwable.
try {
$result = $service->process($input);
} catch (ValidationException $e) {
return $this->badRequest($e->getMessage());
} catch (Throwable $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
return $this->serverError();
} finally {
$this->cleanup();
}What matters in practice:
- Catch
Throwable, notException, when you want a genuine catch-all —TypeErrorandDivisionByZeroErrorareErrors and will slip pastException. - Define your own exception types.
PaymentDeclinedExceptionlets callers handle one failure differently from another; throwing a genericExceptionforces string matching on messages. - Set an exception handler and an error handler at the application's entry point so nothing escapes unlogged, and convert warnings into
ErrorExceptionso they cannot be ignored. - Never show a stack trace to a user.
display_errorsoff in production,log_errorson.
Note: PHP 8 also made many previously-silent warnings into errors — accessing an undefined array key, for example — which is why an upgrade surfaces bugs that were always there.





