Throwable Hierarchy
Throwable is the shared parent type that every error and exception in PHP stands under. A catch for Throwable can catch a value from either branch under it.
A call on null is caught as an Error
The variable holds null, so the method call cannot run. The Error catch receives the failure and prints its class name.
<?php
$thing = null;
try {
$thing->run();
} catch (Error $e) {
echo get_class($e), "\n";
}An Exception skips the Error catch
The try block throws an Exception. The Error catch stays silent, and the Throwable catch prints the verdict line.
<?php
try {
throw new Exception("bad input");
} catch (Error $e) {
echo "error caught\n";
} catch (Throwable $e) {
echo "throwable caught: " . get_class($e) . "\n";
}The tree as two verdicts
The is_subclass_of checks test two links in the tree. Both verdicts print true, so TypeError stands under Error and Exception stands under Throwable.
<?php
var_dump(is_subclass_of(TypeError::class, Error::class));
var_dump(is_subclass_of(Exception::class, Throwable::class));A division error caught as Throwable
The intdiv call divides by zero inside the try block. The Throwable catch prints the class name and the message on one line.
<?php
try {
$x = intdiv(1, 0);
} catch (Throwable $e) {
echo get_class($e) . ": " . $e->getMessage() . "\n";
}Example
<?php
$thing = null;
try {
$thing->run();
} catch (Throwable $e) {
echo "Call: " . get_class($e) . "\n";
}
try {
throw new Exception("stop");
} catch (Throwable $e) {
echo "Throw: " . get_class($e) . "\n";
}
try {
$total = intdiv(10, 0);
} catch (Throwable $e) {
echo "Divide: " . get_class($e) . "\n";
}Key points
- Throwable is the shared parent of the Error branch and the Exception branch.
- A method call on null raises an Error.
- An Error catch does not catch an Exception.
- A Throwable catch catches values from both branches.
- TypeError sits under Error in the tree.
- Exception sits under Throwable in the tree.
In this example, a runner tries three risky calls in a row. The call on null prints Error, the thrown value prints Exception, and the division prints DivisionByZeroError. One Throwable catch shape handles all three tries.
Note
DivisionByZeroError sits under Error, so a Throwable catch can catch it too.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Which catch type catches both an Error and an Exception?