W3docs

catch

As a PHP developer, you may have used the "try...catch" statement to handle errors or exceptions in your code. The "catch" keyword is a key component of the

The PHP catch Keyword

When code inside a try block runs into an exception — an object that signals something went wrong — execution stops and PHP looks for a matching catch block to handle it. The catch keyword names the type of exception it can handle and binds the thrown object to a variable so you can inspect it. Without a catch, an uncaught exception becomes a fatal error and halts the script.

This page explains the catch syntax, how PHP picks which block runs, how to read details off the caught exception, and the common patterns (multiple catches, union types, re-throwing) you will use in real code.

Syntax

A catch block always follows a try block. It declares an exception type and a variable that receives the thrown object:

<?php

try {
    // Code that may throw an exception
} catch (Exception $e) {
    // Runs only if a matching exception is thrown above
    echo $e->getMessage();
}

PHP matches a catch block when the thrown object is an instance of the declared type. Because every built-in exception extends the base Exception class (and both extend the Throwable interface), catch (Exception $e) catches most exceptions. Catching Throwable additionally captures Error objects such as TypeError and DivisionByZeroError.

You can pair catch with a finally block to run cleanup code whether or not an exception occurred.

A working example

The function below throws when asked to divide by zero. The catch block intercepts that exception and reports it instead of letting the script crash:

<?php

function divide($numerator, $denominator)
{
    if ($denominator == 0) {
        throw new InvalidArgumentException("Division by zero.");
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage();
}

// Output: Error: Division by zero.

Notice the script keeps running after the catch — control resumes on the line following the try/catch structure rather than aborting.

Reading details from the caught exception

The variable in a catch clause ($e above) is the exception object itself. It exposes methods that describe what happened:

<?php

try {
    throw new RuntimeException("Disk is full", 28);
} catch (RuntimeException $e) {
    echo $e->getMessage();  // Disk is full
    echo "\n";
    echo $e->getCode();     // 28
    echo "\n";
    echo $e->getLine();     // 4  (line where it was thrown)
}
MethodReturns
getMessage()The human-readable error message
getCode()The integer error code passed to the constructor
getFile()The file in which the exception was created
getLine()The line number where it was thrown
getTrace()The stack trace as an array
getPrevious()The previous exception (for chained exceptions)

Catching multiple exception types

When a try block can fail in different ways, list several catch blocks. PHP tries them top to bottom and runs the first one that matches, so order the more specific types before the general ones:

<?php

try {
    // Code that may throw different exceptions
    throw new InvalidArgumentException("bad input");
} catch (InvalidArgumentException $e) {
    echo "Invalid argument: " . $e->getMessage();
} catch (RuntimeException $e) {
    echo "Runtime problem: " . $e->getMessage();
} catch (Exception $e) {
    echo "Something else: " . $e->getMessage();
}

// Output: Invalid argument: bad input

If catch (Exception $e) came first it would swallow everything, and the more specific blocks below it would never run.

Union catch (PHP 7.1+)

When two different exception types need identical handling, combine them with a pipe | instead of duplicating the block:

<?php

try {
    throw new RuntimeException("connection reset");
} catch (InvalidArgumentException | RuntimeException $e) {
    echo "Handled: " . $e->getMessage();
}

// Output: Handled: connection reset

Non-capturing catch (PHP 8.0+)

If you do not need the exception object, you can omit the variable entirely:

<?php

try {
    throw new Exception("ignored details");
} catch (Exception) {
    echo "An error occurred, retrying...";
}

// Output: An error occurred, retrying...

Re-throwing and exception chaining

Sometimes a catch block should log the problem and then pass it on — or wrap a low-level exception in a more meaningful one. Pass the original as the third constructor argument to preserve the chain:

<?php

try {
    try {
        throw new RuntimeException("low-level failure");
    } catch (RuntimeException $e) {
        // Wrap and re-throw with context preserved
        throw new Exception("High-level operation failed", 0, $e);
    }
} catch (Exception $e) {
    echo $e->getMessage();              // High-level operation failed
    echo "\n";
    echo $e->getPrevious()->getMessage(); // low-level failure
}

Best practices

  • Catch the narrowest type you can handle. A blanket catch (Throwable $e) can hide bugs by swallowing programming errors you meant to fix.
  • Order specific before general. Specific subclasses must precede their parent types.
  • Don't leave a catch empty. Silently discarding an exception makes failures invisible; at minimum log it.
  • Throw, don't return error flags. Combine catch with throw so callers can't accidentally ignore failures.
  • Use finally for cleanup (closing files, releasing locks) that must run on both the success and failure paths.

Practice

Practice
What happens when an exception is thrown and not caught in PHP?
What happens when an exception is thrown and not caught in PHP?
Was this page helpful?