W3docs

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 loaded

The 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

  • try needs a partner. A try block alone won't parse — pair it with at least one catch or a finally.
  • Errors aren't all exceptions. Many runtime warnings (an undefined variable, a failed fopen()) are not thrown as exceptions, so catch won't see them. Use set_error_handler() or check return values for those. Fatal Error objects (like TypeError) can be caught because they implement Throwable.
  • Order your catch blocks specific-first. A broad catch (Exception $e) placed first hides every later block.
  • Don't swallow silently. An empty catch block hides the failure; at minimum log $e->getMessage() so the problem is visible.
  • finally can mask exceptions. Returning from finally discards both the try return 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.

Practice

Practice
What tag is used in PHP to start a code block?
What tag is used in PHP to start a code block?
Was this page helpful?