PHP Exceptions
Exceptions are how errors propagate up the call stack. try the risky code, catch a specific exception class, finally clean up.
The shape
PHP
try {
$config = json_decode($input, true, flags: JSON_THROW_ON_ERROR);
process($config);
} catch (JsonException $e) {
echo 'Bad JSON: ', $e->getMessage();
} catch (RuntimeException $e) {
echo 'Run-time problem: ', $e->getMessage();
} finally {
cleanup(); // runs whether we caught or not
}
Throw your own
PHP
function deposit(int $cents): void {
if ($cents <= 0) {
throw new InvalidArgumentException("cents must be positive: $cents");
}
// ...
}
Define a custom exception
PHP
class PaymentDeclined extends RuntimeException
{
public function __construct(
public readonly string $reason,
?\Throwable $previous = null,
) {
parent::__construct("Payment declined: $reason", 0, $previous);
}
}
throw new PaymentDeclined('Card expired');
Standard exception hierarchy
Throwable ← interface
├── Error ← engine-level failures (don't catch)
│ ├── TypeError
│ ├── ValueError
│ └── …
└── Exception ← user-land
├── RuntimeException
├── LogicException
│ ├── InvalidArgumentException
│ ├── DomainException
│ └── …
└── (your own)
Anti-patterns
catch (Exception $e)by itself swallows too much. Catch the most specific subclass that fits.- Catching and ignoring (
catch (X $e) {}) hides bugs. At minimum log it. - Using exceptions for normal control flow — they're for exceptional cases.
Re-throwing with context
PHP
try {
$api->send($payload);
} catch (NetworkException $e) {
throw new SyncFailed("Couldn't reach API", previous: $e);
}
Tip: A global error handler (Sentry, Bugsnag, framework's own logger) catches what your code doesn't. Let exceptions bubble; let the handler decide what to do with them.
Example
Example
<?php
try {
if (random_int(0, 1) === 0) {
throw new RuntimeException('Oops');
}
echo 'OK';
} catch (RuntimeException $e) {
echo 'Caught: ', $e->getMessage();
} finally {
echo PHP_EOL, 'cleanup';
}
Try it Yourself »
Exercise
Catch a specific exception type.
(JsonException $e) { echo $e->getMessage(); }
Five letters.
Discussion
Loading…