An exception is an object that represents a problem. When something goes wrong, code can throw an exception. The program stops its normal flow and jumps to the nearest piece of code that knows how to catch it.
Compared with a plain warning, an exception lets you decide what to do: show a message, retry, log it or stop.
<?php
function divide(int $a, int $b): float
{
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero.");
}
return $a / $b;
}
try {
echo divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Problem: " . $e->getMessage();
}
Problem: Cannot divide by zero.
The hierarchy
All throwable things share one interface, Throwable. It has two branches:
Throwable
├── Exception (problems your code can expect and handle)
│ ├── LogicException
│ │ ├── InvalidArgumentException
│ │ ├── DomainException
│ │ └── LengthException ...
│ ├── RuntimeException
│ │ ├── OutOfBoundsException
│ │ ├── UnexpectedValueException
│ │ └── OverflowException ...
│ ├── JsonException
│ └── ErrorException
└── Error (serious problems in the code itself, thrown by PHP)
├── TypeError
├── ValueError
├── ArithmeticError
│ └── DivisionByZeroError
├── ArgumentCountError
└── UnhandledMatchError
Exception vs Error
- Exception: something went wrong at run time that your program might recover from (a file is missing, bad input).
- Error: a mistake in the code or a broken rule (wrong type, undefined function). PHP 7 turned most fatal errors into
Errorobjects, which you can catch if you must.
To catch both, catch Throwable.
<?php
try {
echo intdiv(1, 0);
} catch (DivisionByZeroError $e) {
echo get_class($e) . ": " . $e->getMessage();
}
DivisionByZeroError: Division by zero
What an exception holds
<?php
try {
throw new RuntimeException("Disk full", 507);
} catch (RuntimeException $e) {
echo $e->getMessage() . "\n"; // the text
echo $e->getCode() . "\n"; // an optional number
echo basename($e->getFile()) . "\n";
echo $e->getLine(); // where it was created
}
Disk full
507
index.php
3
getTraceAsString() returns the chain of calls that led there, which is very useful when you debug (and sensitive when you show it to visitors).
Which class should I throw?
| Situation | Class |
|---|---|
| A function got a bad argument | InvalidArgumentException |
| A value is outside the allowed range | OutOfRangeException or DomainException |
| Something failed at run time (file, network) | RuntimeException |
| A bug in the program logic | LogicException |
| Decoding JSON failed | JsonException |
Or write your own, as shown in Custom Exceptions.
An uncaught exception
If no catch handles it, PHP stops with a fatal error. On a live site that should show a friendly page, not the technical message (see Production Error Handling).
Throw, do not return false
false for failure is easy to forget to check. An exception cannot be ignored by accident, so failures are hard to miss.