Back to Blog
Lesson 48 of the PHP: Modern PHP from the Ground Up course
PHPSeptember 5, 20264 min read

Error Handling with Exceptions: A Guide for PHP Beginners

Stop relying on return values for error checking. Learn to use PHP exceptions and try-catch blocks to build professional, failure-resistant applications.

PHPerror handlingexceptionsbackendprogramming patterns
Close-up of PHP code on a monitor, highlighting development and programming concepts.

Previously in this course, we covered working with dates and time to manage temporal data in our applications. While dates are predictable, user input and database operations are not; this lesson moves us from simple conditional error checks to professional error handling using exceptions.

In early programming, we often checked for errors by verifying return values—like checking if a database query returned false. This leads to "arrow code," where your business logic is buried under nested if statements. Exceptions allow us to separate the "happy path" (your main logic) from the "error path" (how you handle failure).

Understanding Exceptions from First Principles

An exception is an object that represents an error condition. When an operation cannot be completed, you "throw" an exception to stop the current process. This immediately halts the normal execution flow and looks for a "catch" block to handle the situation.

Think of it like a fire alarm in a building. The alarm (exception) interrupts everyone's work (code execution) and triggers a specific emergency procedure (the catch block).

Using Try-Catch Blocks

The try-catch construct is the core of modern error handling. You wrap the code that might fail inside a try block. If an exception occurs, execution jumps to the catch block, where you can log the error or notify the user.

PHP
try {
    #6A9955">// Code that might fail
    $user = $userModel->findById(999);
    if (!$user) {
        throw new Exception("User not found.");
    }
} catch (Exception $e) {
    #6A9955">// Code to handle the error
    echo "Error: " . $e->getMessage();
}

The $e variable in the catch block is an instance of the Exception class. It provides methods like getMessage(), getCode(), and getFile() to help you diagnose what happened.

Creating Custom Exception Handlers

While generic Exception classes are useful, they aren't very descriptive. In a professional application, you should create custom exceptions. This allows you to catch specific errors differently (e.g., a "ValidationException" should show a form, while a "DatabaseException" might just show a generic 500 error).

PHP
class UserNotFoundException extends Exception {}

#6A9955">// Usage in your Model
public function findById(int $id) {
    $result = $this->db->query("SELECT * FROM users WHERE id = ?", [$id]);
    if (!$result) {
        throw new UserNotFoundException("User with ID $id does not exist.");
    }
    return $result;
}

You can then catch this specific error:

PHP
try {
    $user = $userModel->findById(999);
} catch (UserNotFoundException $e) {
    #6A9955">// Specific logic for missing users
    header("Location: /404");
} catch (Exception $e) {
    #6A9955">// Catch-all for other unexpected errors
    error_log($e->getMessage());
    echo "Something went wrong.";
}

Comparing Error Strategies

ApproachProsCons
Return CodesSimple, explicitVerbose, easy to ignore
ExceptionsClean flow, forced handlingCan be overused for logic

Hands-on Exercise

In your current MVC project, locate your database connection or model fetching logic. Instead of returning false when a record is not found, define a custom RecordNotFoundException class. Update your controller to try-catch this exception and redirect the user to a friendly 404 page if the record is missing.

Common Pitfalls

  1. Empty Catch Blocks: Never leave a catch block empty. If you aren't going to handle the error, at least log it using error_log(). Failing to do so makes your app impossible to debug.
  2. Catching Everything: Don't catch Throwable or Exception everywhere. Only catch exceptions you can actually recover from; otherwise, let them bubble up to a global handler.
  3. Using Exceptions for Control Flow: Exceptions should represent exceptional events (errors), not standard logic (like checking if a password is correct). Use if-else for standard business logic.

Frequently Asked Questions

Can I throw exceptions inside a constructor? Yes, and it is a best practice. If an object cannot be initialized with valid data, throwing an exception prevents the creation of an "invalid" object.

What happens if I don't catch an exception? The script will terminate immediately, and PHP will display a fatal error message. In production, this can leak sensitive server paths, so always ensure you have a global exception handler.

Recap

Exceptions provide a clean way to manage errors by decoupling detection from resolution. By using try-catch blocks and defining custom exceptions, you keep your MVC controllers focused on the request path rather than cluttered with error-checking boilerplate.

Up next: We will learn how to leverage external code by using third-party libraries via Composer.

Similar Posts