PHP Error Handling
Things go wrong: a file is missing, a division is invalid, an API times out. PHP gives you try/catch/finally to handle these situations gracefully instead of letting the whole script crash with a raw error message.
1) try / catch / finally
Code that might fail goes in try. If it throws, execution jumps to the matching
catch. The finally block always runs afterward, whether or not an exception
was thrown — useful for cleanup like closing a file or a database connection.
<?php
try {
$result = riskyOperation();
} catch (Exception $e) {
echo 'Something went wrong: ' . $e->getMessage();
} finally {
// runs no matter what
closeConnection();
}
?>
2) Throwing Exceptions
Use throw new Exception('message') to signal that something went wrong in a way the caller can catch and react to.
<?php
function withdraw(float $balance, float $amount): float {
if ($amount > $balance) {
throw new Exception('Insufficient funds.');
}
return $balance - $amount;
}
?>
3) Custom Exception Classes
Extend the built-in Exception class to create a specific, catchable type — useful when
different failure kinds need different handling.
<?php
class InvalidAgeException extends Exception {}
function setAge(int $age): void {
if ($age < 0 || $age > 150) {
throw new InvalidAgeException("Age {$age} is not valid.");
}
}
?>
This page defines a similar custom exception, DivisionByZeroDemoException, used in the live demo below.
4) Live Demo: A Custom Exception in try/catch
<?php
class DivisionByZeroDemoException extends Exception {}
function safeDivide(float $a, float $b): float {
if ($b === 0.0) {
throw new DivisionByZeroDemoException("Cannot divide {$a} by zero.");
}
return $a / $b;
}
?>
| Call | try/catch outcome (real, live) |
|---|---|
safeDivide(10, 2) — valid |
Result: 5 (no exception thrown)
|
safeDivide(10, 0) — deliberately invalid |
Caught exception message: Cannot divide 10 by zero.
|
DivisionByZeroDemoException, which was really caught above instead of crashing the page.5) Errors vs Exceptions
| Errors | Exceptions | |
|---|---|---|
| Typical cause | Calling an undefined function, type errors, out of memory | Application-level failures you anticipate (bad input, failed lookup) |
| Can you catch it? | Some (via Error class in PHP 7+), but often fatal | Yes, always — that's their purpose |
| Typical use | Indicates a bug in the code | Indicates an expected-but-exceptional situation to recover from |
6) error_reporting() and display_errors: Dev vs Production
In development you want to see every notice and warning. In production you must never show raw errors to visitors (they can leak file paths, queries, or secrets) — log them to a file instead.
<?php
// Development (php.ini or top of a dev bootstrap file)
error_reporting(E_ALL);
ini_set('display_errors', '1');
// Production
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', '/var/log/php/app-errors.log');
?>
finally, create custom exception classes for distinct failure types, and keep
display_errors off in production — log instead.