try
Learn how PHP try/catch/finally handles exceptions. Covers multiple catch blocks, union types, rethrowing, and common pitfalls.
The PHP try Keyword
The try keyword marks a block of code that might throw an exception — an object signalling that something went wrong and normal execution cannot continue. When an exception is thrown inside a try block, PHP stops running the rest of that block and looks for a matching catch block to handle it. An optional finally block then runs no matter what happened.
This page covers the try/catch/finally syntax, how multiple catch blocks are matched, catching several exception types at once, rethrowing, and the gotchas that trip people up. If you are new to the idea of throwing errors, read Exceptions in PHP first.
Syntax
try {
// Code that may throw an exception
} catch (ExceptionType $e) {
// Code that runs if an exception of ExceptionType (or a subclass) is thrown
} finally {
// Optional: always runs, whether or not an exception was thrown
}A try block must be followed by at least one catch block, or a finally block, or both — a try on its own is a syntax error. The variable in catch (ExceptionType $e) holds the thrown exception object, which you query with methods such as $e->getMessage().
A first example
The function below throws an exception when asked to divide by zero. The try block calls it, the catch block reports the problem, and finally always runs:
<?php
function divide($dividend, $divisor)
{
if ($divisor == 0) {
throw new Exception("Cannot divide by zero.");
}
return $dividend / $divisor;
}
try {
$result = divide(10, 0);
echo $result; // skipped — divide() threw before returning
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . PHP_EOL;
} finally {
echo "Done." . PHP_EOL;
}Output:
Error: Cannot divide by zero.
Done.Notice that echo $result; never runs: once divide(10, 0) throws, control jumps straight to the catch block. The finally block runs afterwards. If you call divide(10, 2) instead, no exception is thrown, the try block prints 5, and finally still prints Done..
Multiple catch blocks
A single try can be followed by several catch blocks. PHP checks them top to bottom and runs the first one whose type matches the thrown exception (matching includes subclasses). List more specific types before more general ones — a leading catch (Exception $e) would swallow everything below it.
<?php
try {
$value = "5";
if (!is_int($value)) {
throw new TypeError("Expected an integer.");
}
} catch (TypeError $e) {
echo "Type problem: " . $e->getMessage() . PHP_EOL;
} catch (Exception $e) {
echo "Other problem: " . $e->getMessage() . PHP_EOL;
}Output:
Type problem: Expected an integer.Catching several types in one block
When two exception types should be handled the same way, combine them with a vertical bar (|) — a feature added in PHP 7.1 — instead of duplicating the block:
<?php
try {
throw new RuntimeException("Network timed out.");
} catch (RuntimeException | LogicException $e) {
echo "Handled: " . $e->getMessage() . PHP_EOL;
}Output:
Handled: Network timed out.How finally behaves
The finally block runs even if the try or catch block executes a return. This makes it the right place for cleanup — closing files, releasing locks, rolling back a transaction — that must happen on every path:
<?php
function readConfig()
{
try {
return "config loaded";
} finally {
echo "Cleanup ran." . PHP_EOL;
}
}
echo readConfig() . PHP_EOL;Output:
Cleanup ran.
config loadedThe finally block executes before the function actually returns its value. Avoid returning from finally itself: a return there overrides the value from try/catch and silently discards any exception that was being thrown.
Rethrowing an exception
A catch block can do partial work — log the error, add context — and then rethrow so a caller higher up can decide what to do. Use throw $e; to rethrow the same object:
<?php
try {
try {
throw new Exception("Disk full.");
} catch (Exception $e) {
echo "Logging: " . $e->getMessage() . PHP_EOL;
throw $e; // hand it to the outer handler
}
} catch (Exception $e) {
echo "Outer handler: " . $e->getMessage() . PHP_EOL;
}Output:
Logging: Disk full.
Outer handler: Disk full.Common gotchas
tryneeds a partner. Atryblock alone won't parse — pair it with at least onecatchor afinally.- Errors aren't all exceptions. Many runtime warnings (an undefined variable, a failed
fopen()) are not thrown as exceptions, socatchwon't see them. Useset_error_handler()or check return values for those. FatalErrorobjects (likeTypeError) can be caught because they implementThrowable. - Order your
catchblocks specific-first. A broadcatch (Exception $e)placed first hides every later block. - Don't swallow silently. An empty
catchblock hides the failure; at minimum log$e->getMessage()so the problem is visible. finallycan mask exceptions. Returning fromfinallydiscards both thetryreturn value and any in-flight exception.
When should I use try?
Reach for try/catch when a failure is exceptional and the calling code can reasonably react to it: a database connection that drops, an API that returns an error, invalid user input you want to reject cleanly. For ordinary control flow (was a key found in an array? is a string empty?), use normal conditionals — exceptions are for the abnormal path, not everyday branching.
Related
catch— the block that handles a thrown exception.finally— code that always runs aftertry/catch.throw— raise an exception yourself.- The Exception class — the base type and its methods.
- Exceptions in PHP — the bigger picture of error handling.
set_exception_handler()— catch exceptions that escape everytry.