PHP 8 has a unified Throwable hierarchy. Understanding it lets you write robust, failure-resilient applications.
Throwable
├── Error (engine-level)
│ ├── TypeError
│ ├── ValueError
│ └── ArithmeticError
└── Exception (application-level)
├── RuntimeException
├── InvalidArgumentException
├── LogicException
└── ... custom exceptions
try {
riskyOperation();
} catch (InvalidArgumentException $e) {
echo "Bad input: " . $e->getMessage();
} catch (RuntimeException | LogicException $e) {
echo "App error: " . $e->getMessage();
} catch (Throwable $e) {
echo "Unexpected: " . $e->getMessage();
} finally {
echo "Always runs.";
}
class NotFoundException extends RuntimeException {
public function __construct(string $resource, int|string $id) {
parent::__construct(
"$resource #$id not found.",
404
);
}
}
function findUser(int $id): array {
$user = queryDb($id);
if (!$user) {
throw new NotFoundException("User", $id);
}
return $user;
}
try {
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
echo "Invalid JSON: " . $e->getMessage();
}