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.

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.
PHPtry { #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).
PHPclass 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:
PHPtry { $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
| Approach | Pros | Cons |
|---|---|---|
| Return Codes | Simple, explicit | Verbose, easy to ignore |
| Exceptions | Clean flow, forced handling | Can 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
- Empty Catch Blocks: Never leave a
catchblock empty. If you aren't going to handle the error, at least log it usingerror_log(). Failing to do so makes your app impossible to debug. - Catching Everything: Don't catch
ThrowableorExceptioneverywhere. Only catch exceptions you can actually recover from; otherwise, let them bubble up to a global handler. - Using Exceptions for Control Flow: Exceptions should represent exceptional events (errors), not standard logic (like checking if a password is correct). Use
if-elsefor 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.
Work with me

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs — the backend engine for your app, mobile client, or SaaS. Built by an API specialist.

FilamentPHP Admin Panel & Dashboard Development
A powerful admin panel for your Laravel app — built with FilamentPHP so you can manage everything without touching the database.


