PHP has two systems for reporting problems: exceptions, which unwind the stack and can
be caught, and the older error levels, which are reported through a handler. Since PHP
7.0 most engine errors are thrown as objects of the class Error. See the
manual on
Exceptions and
Error handling.
The Throwable hierarchy
Every object that can be thrown implements Throwable
(PHP 7.0). A class cannot
implement it directly: it must extend Exception or Error.
An interface may extend Throwable.
Throwable
├── Error engine and programming errors
│ ├── ArithmeticError
│ │ └── DivisionByZeroError
│ ├── AssertionError
│ ├── CompileError
│ │ └── ParseError
│ ├── FiberError
│ ├── TypeError
│ │ └── ArgumentCountError
│ ├── UnhandledMatchError
│ └── ValueError
└── Exception conditions a program may want to handle
├── ErrorException
├── ClosedGeneratorException
├── JsonException
├── RequestParseBodyException
├── LogicException
│ ├── BadFunctionCallException
│ │ └── BadMethodCallException
│ ├── DomainException
│ ├── InvalidArgumentException
│ ├── LengthException
│ └── OutOfRangeException
└── RuntimeException
├── OutOfBoundsException
├── OverflowException
├── RangeException
├── UnderflowException
└── UnexpectedValueException
PDOException| Class | Thrown when |
|---|---|
TypeError | A value has the wrong type for a parameter, return value or property |
ArgumentCountError | Too few arguments are passed |
ValueError | An argument has the right type but an invalid value (PHP 8.0) |
ArithmeticError | An arithmetic error, such as a negative shift or PHP_INT_MIN divided by -1 |
DivisionByZeroError | Division or modulo by zero |
UnhandledMatchError | A match has no matching arm |
ParseError | eval() or an include finds invalid syntax |
AssertionError | assert() fails and assertions throw |
Error | Other engine errors, such as calling an undefined function or reading an uninitialised typed property |
ErrorException | Thrown by code to turn a traditional error into an exception |
JsonException | json_encode() or json_decode() fails with JSON_THROW_ON_ERROR |
Throwable declares getMessage(), getCode(),
getFile(), getLine(), getTrace(),
getTraceAsString(), getPrevious() and
__toString(). The Exception constructor takes an optional
message, code and previous exception, the last of which chains one exception to its
cause.
try, catch and finally
try { statements }
{catch ( Class {| Class} [$var] ) { statements }}
[finally { statements }]
try {
$data = load($path);
} catch (FileNotFound | Forbidden $e) {
log_warning($e->getMessage());
$data = [];
} catch (Exception) {
throw new RuntimeException('load failed');
} finally {
release_lock();
}
- A
tryneeds at least onecatchor afinally. catchclauses are tried in order, and the first matching one runs.- A
catchcan name several types separated by|(PHP 7.1). - The variable may be left out (PHP 8.0) if the exception is not used.
- To catch everything use
catch (Throwable $e). Acatch (Exception $e)does not catch anError. - A
finallyblock (PHP 5.5) runs whether or not an exception was thrown and even after areturn. Areturninsidefinallyreplaces any earlier return value and discards an exception in flight.
throw
throw raises an object that implements Throwable; throwing
anything else is an Error. Since
PHP 8.0 it is an expression, so it can be used in arrow functions and on the right of
??, ?: and match.
$value = $input ?? throw new InvalidArgumentException('missing');
$fail = fn() => throw new LogicException('not implemented');
An uncaught exception ends the script with a fatal error unless a handler has been
set with set_exception_handler(). Finally blocks and shutdown functions
still run.
Error levels
Traditional errors are not objects. Each has a level, and
error_reporting selects which levels are reported.
| Constant | Value | Meaning |
|---|---|---|
E_ERROR | 1 | Fatal run-time error; the script stops |
E_WARNING | 2 | Non-fatal run-time warning |
E_PARSE | 4 | Compile-time parse error |
E_NOTICE | 8 | Possible problem at run time |
E_CORE_ERROR | 16 | Fatal error during start-up |
E_CORE_WARNING | 32 | Warning during start-up |
E_COMPILE_ERROR | 64 | Fatal compile-time error |
E_COMPILE_WARNING | 128 | Compile-time warning |
E_USER_ERROR | 256 | Raised by trigger_error(). Passing it is deprecated since 8.4 |
E_USER_WARNING | 512 | Raised by trigger_error() |
E_USER_NOTICE | 1024 | Raised by trigger_error() |
E_STRICT | 2048 | Unused. The constant is deprecated since 8.4 |
E_RECOVERABLE_ERROR | 4096 | Catchable fatal error, with a handler |
E_DEPRECATED | 8192 | Feature that will be removed |
E_USER_DEPRECATED | 16384 | Raised by trigger_error() |
E_ALL | 30719 | All of them. 32767 before 8.4, which included E_STRICT |
Values combine as a bitmask: error_reporting(E_ALL & ~E_DEPRECATED).
Handlers
| Function | Handles |
|---|---|
set_error_handler() | Non-fatal errors. It may turn them into exceptions by throwing ErrorException |
set_exception_handler() | An exception that nothing caught |
register_shutdown_function() | Runs when the script ends, including after a fatal error. error_get_last() gives the last error |
A user error handler is not called for fatal errors such as E_ERROR,
E_PARSE, and the core and compile-time errors.
The @ operator
The prefix @ hides errors raised while evaluating an expression. Since
PHP 8.0 it no longer hides fatal errors, and it does not stop exceptions at all.
Whether errors reach the browser or a log is decided by the
display_errors and
log_errors settings.