11: Error and Exception Handling

Chapter 11: Error and Exception Handling
Section titled “Chapter 11: Error and Exception Handling”Overview
Section titled “Overview”No matter how carefully we code, things can and will go wrong. A user might provide invalid input, a file we need to read might not exist, or a database connection could fail. If we don’t plan for these situations, our scripts will crash and show ugly error messages to the user.
Error handling is the process of anticipating and managing these problems. In modern PHP, the primary way we do this is with exceptions. An exception is an object that is “thrown” when an error occurs, interrupting the normal flow of the program and allowing us to “catch” it and handle the problem gracefully.
By the end of this chapter, you’ll build a robust bank account system that validates withdrawals, handles errors gracefully, and provides clear feedback when operations fail—all without crashing your application.
Prerequisites
Section titled “Prerequisites”- PHP 8.4 installed and accessible from your terminal (PHP 7.1+ for multi-catch syntax)
- Completion of previous chapters, especially Chapter 10 (OOP, Traits, and Namespaces)
- A text editor and command line
- Estimated time: 35–40 minutes
What You’ll Build
Section titled “What You’ll Build”- A division function that safely handles zero division
- Exception handling with
try,catch, andfinallyblocks - A custom
InsufficientFundsExceptionclass - A
BankAccountclass that throws and handles domain-specific exceptions - Working examples demonstrating graceful error recovery
Objectives
Section titled “Objectives”- Understand the difference between traditional errors and modern exceptions.
- Use a
try...catchblock to handle exceptions and prevent application crashes. - “Throw” your own exceptions when something goes wrong in your code.
- Use the
finallyblock to run cleanup code, regardless of whether an exception occurred. - Create custom exception classes for more specific error handling.
Step 1: The Problem: A Fatal Error (~3 min)
Section titled “Step 1: The Problem: A Fatal Error (~3 min)”Let’s look at what happens when an operation fails without any error handling.
Demonstrate how unhandled errors crash your application and prevent subsequent code from running.
Actions
Section titled “Actions”-
Create a File: Create a new file
exceptions.phpin your working directory. -
Write Code that Fails: Let’s write a function that divides two numbers. Division by zero is a mathematical impossibility and will cause a fatal error.
<?phpdeclare(strict_types=1);
function divide(int $numerator, int $denominator): float{ return $numerator / $denominator;}
echo divide(10, 2); // This worksecho PHP_EOL;echo divide(5, 0); // This will crashecho "This line will never be reached." . PHP_EOL;- Run the Script:
# Run the failing scriptphp exceptions.phpExpected Result
Section titled “Expected Result”5
Fatal error: Uncaught DivisionByZeroError: Division by zero in exceptions.php:6Stack trace:#0 exceptions.php(12): divide(5, 0)#1 {main} thrown in exceptions.php on line 6The script prints 5 (from the first division), then crashes immediately when it tries to divide by zero. The final echo statement never executes.
Why It Works (or Doesn’t)
Section titled “Why It Works (or Doesn’t)”PHP 8.0+ automatically throws a DivisionByZeroError when you divide by zero. Without a try...catch block, this error is uncaught, causing the script to terminate abruptly. The user sees a technical stack trace instead of a helpful message.
Troubleshooting
Section titled “Troubleshooting”Problem: Script doesn’t crash and shows INF or a warning instead.
Solution: Ensure you’re using PHP 8.0 or later. Earlier versions had different behavior for division by zero.
Step 2: Throwing and Catching Exceptions (~5 min)
Section titled “Step 2: Throwing and Catching Exceptions (~5 min)”Instead of letting the script crash, we can detect the problem and throw an exception. Then, we can wrap the “risky” code that might cause the problem in a try block and handle the potential error in a catch block.
Gracefully handle errors by catching exceptions and allowing the application to continue running.
Actions
Section titled “Actions”- Update Your Script:
Replace the contents of
exceptions.phpwith the following:
<?phpdeclare(strict_types=1);
function divide(int $numerator, int $denominator): float{ if ($denominator === 0) { // Instead of causing a fatal error, we throw an exception object. // `Exception` is a built-in PHP class. throw new Exception("Cannot divide by zero!"); } return $numerator / $denominator;}
// We "try" the code that might throw an exception.try { echo divide(10, 2) . PHP_EOL; echo divide(5, 0) . PHP_EOL; // This line will throw the exception echo "This line will never be reached." . PHP_EOL;} catch (Exception $e) { // If an exception is thrown inside the `try` block, // execution jumps to this `catch` block. // The exception object is passed as the argument `$e`. echo "An error occurred: " . $e->getMessage() . PHP_EOL;}
echo "The application continues to run." . PHP_EOL;- Run the Script:
# Run the improved scriptphp exceptions.phpExpected Result
Section titled “Expected Result”5An error occurred: Cannot divide by zero!The application continues to run.The script now handles the error gracefully, displays a user-friendly message, and continues executing.
Why It Works
Section titled “Why It Works”The try block wraps potentially dangerous code. When throw new Exception() is executed inside the try block, PHP immediately stops executing that block and jumps to the matching catch block. The exception object (stored in $e) contains the error message we provided. The getMessage() method retrieves it. After the catch block completes, normal execution resumes—the application doesn’t crash.
Troubleshooting
Section titled “Troubleshooting”Problem: “Class ‘Exception’ not found” error.
Solution: Ensure your PHP installation is correct. Exception is a built-in class available in all PHP versions.
Problem: The application still crashes.
Solution: Make sure your throw statement is inside the try block scope. If you call divide() outside the try block, the exception won’t be caught.
Step 3: The finally Block (~4 min)
Section titled “Step 3: The finally Block (~4 min)”Sometimes, there’s a piece of code that you always want to run, whether an exception was thrown or not. This is often used for cleanup tasks, like closing a database connection or a file handle. The finally block is perfect for this.
Learn to use the finally block for cleanup code that must run regardless of success or failure.
Actions
Section titled “Actions”- Create a New File:
Create
finally-demo.php:
<?phpdeclare(strict_types=1);
function divide(int $numerator, int $denominator): float{ if ($denominator === 0) { throw new Exception("Cannot divide by zero!"); } return $numerator / $denominator;}
try { echo "Trying to divide by 2..." . PHP_EOL; echo divide(10, 2) . PHP_EOL;
echo "Trying to divide by 0..." . PHP_EOL; echo divide(5, 0) . PHP_EOL;} catch (Exception $e) { echo "Caught exception: " . $e->getMessage() . PHP_EOL;} finally { // This code runs whether an exception was caught or not. echo "This is the finally block. It always runs." . PHP_EOL;}
echo "Script completed." . PHP_EOL;- Run the Script:
# Run the finally demonstrationphp finally-demo.phpExpected Result
Section titled “Expected Result”Trying to divide by 2...5Trying to divide by 0...Caught exception: Cannot divide by zero!This is the finally block. It always runs.Script completed.Why It Works
Section titled “Why It Works”The finally block executes after the try and catch blocks, regardless of whether an exception was thrown. This makes it ideal for cleanup operations like:
- Closing file handles
- Releasing database connections
- Logging operations
- Resetting state
Even if you add a return statement in the try or catch block, the finally block still runs before the function returns.
Troubleshooting
Section titled “Troubleshooting”Problem: The finally block doesn’t run.
Solution: Check that you’ve correctly structured your try-catch-finally blocks. The finally keyword must be at the same indentation level as try and catch.
::: tip
The finally block runs even if there’s a return statement in the try or catch blocks, making it perfect for guaranteed cleanup operations.
:::
Step 4: Creating Custom Exceptions (~6 min)
Section titled “Step 4: Creating Custom Exceptions (~6 min)”PHP has many built-in exception types (DivisionByZeroError, TypeError, etc.), but it’s a great practice to create your own for your application’s specific logic. This allows you to catch different types of errors separately and handle them appropriately.
Build a bank account system with custom exceptions for domain-specific errors.
Actions
Section titled “Actions”A custom exception is simply a class that extends the base Exception class.
- Create a New File:
Create
bank-account.php:
<?phpdeclare(strict_types=1);
// A custom exception class for insufficient fundsclass InsufficientFundsException extends Exception {}
class BankAccount{ // PHP 8.0+ constructor property promotion public function __construct(private float $balance) {}
public function withdraw(float $amount): void { if ($amount <= 0) { throw new Exception("Withdrawal amount must be positive."); }
if ($amount > $this->balance) { // Throw our specific exception type throw new InsufficientFundsException( "Cannot withdraw $$amount. Insufficient funds." ); }
$this->balance -= $amount; }
public function getBalance(): float { return $this->balance; }}
// Demonstration$account = new BankAccount(100);
try { $account->withdraw(50); echo "Withdrawal successful. New balance: $" . $account->getBalance() . PHP_EOL;
$account->withdraw(75); // This will throw InsufficientFundsException echo "This line won't execute." . PHP_EOL;
} catch (InsufficientFundsException $e) { // We can specifically catch *our* custom exception echo "Transaction failed: " . $e->getMessage() . PHP_EOL; echo "Current balance remains: $" . $account->getBalance() . PHP_EOL;} catch (Exception $e) { // A general catch block for any other type of exception echo "A general error occurred: " . $e->getMessage() . PHP_EOL;}
echo "Application continues running normally." . PHP_EOL;- Run the Script:
# Run the bank account demonstrationphp bank-account.phpExpected Result
Section titled “Expected Result”Withdrawal successful. New balance: $50Transaction failed: Cannot withdraw $75. Insufficient funds.Current balance remains: $50Application continues running normally.Why It Works
Section titled “Why It Works”By creating a custom InsufficientFundsException class, you can:
- Catch specific errors: The first
catchblock only handles insufficient funds errors, allowing you to provide specific feedback. - Separate concerns: Different exception types can be handled differently—maybe insufficient funds gets logged differently than invalid input.
- Improve readability:
InsufficientFundsExceptionis far more descriptive than a genericException. - Add custom behavior: You can add properties and methods to your custom exceptions (e.g., store the attempted amount and current balance).
The order of catch blocks matters: PHP checks them top-to-bottom and executes the first match. Always catch more specific exceptions before generic ones.
Troubleshooting
Section titled “Troubleshooting”Problem: The generic Exception catch block is triggered instead of the custom one.
Solution: Ensure the custom exception extends Exception and that you’re throwing the correct exception type. Also, check that the more specific catch block comes before the generic one.
Problem: “Constructor property promotion” syntax error.
Solution: Constructor property promotion (private float $balance in the constructor) requires PHP 8.0+. Verify your version with php --version.
::: tip
You can extend your custom exceptions with additional methods and properties. For example, InsufficientFundsException could have a getAttemptedAmount() method to provide more context for error handling.
:::
Step 5: Built-in SPL Exceptions (~5 min)
Section titled “Step 5: Built-in SPL Exceptions (~5 min)”PHP provides a rich set of built-in exception types through the Standard PHP Library (SPL). These exceptions are more semantically meaningful than the generic Exception class and are widely used in professional PHP code.
Learn when to use SPL exceptions and refactor code to use more specific exception types.
Actions
Section titled “Actions”- Create a New File:
Create
spl-exceptions.php:
<?phpdeclare(strict_types=1);
/** * Demonstrates proper use of SPL exception types */
class Calculator{ public function divide(int $numerator, int $denominator): float { if ($denominator === 0) { // InvalidArgumentException is more specific than Exception throw new InvalidArgumentException( "Denominator cannot be zero." ); }
return $numerator / $denominator; }
public function getFactorial(int $number): int { if ($number < 0) { throw new InvalidArgumentException( "Factorial is not defined for negative numbers." ); }
if ($number > 20) { throw new OutOfRangeException( "Number too large. Maximum supported value is 20." ); }
$result = 1; for ($i = 2; $i <= $number; $i++) { $result *= $i; }
return $result; }}
$calc = new Calculator();
// Example 1: Catching InvalidArgumentExceptiontry { echo "5 / 2 = " . $calc->divide(5, 2) . PHP_EOL; echo "5 / 0 = " . $calc->divide(5, 0) . PHP_EOL;} catch (InvalidArgumentException $e) { echo "Invalid argument: " . $e->getMessage() . PHP_EOL;}
// Example 2: Catching multiple exception types (PHP 7.1+)try { echo "Factorial of 5: " . $calc->getFactorial(5) . PHP_EOL; echo "Factorial of 25: " . $calc->getFactorial(25) . PHP_EOL;} catch (InvalidArgumentException | OutOfRangeException $e) { // Both exception types handled here echo "Error: " . $e->getMessage() . PHP_EOL;}
// Example 3: Exception object methodstry { $calc->divide(10, 0);} catch (InvalidArgumentException $e) { echo "Exception Details:" . PHP_EOL; echo " Message: " . $e->getMessage() . PHP_EOL; echo " Code: " . $e->getCode() . PHP_EOL; echo " File: " . $e->getFile() . PHP_EOL; echo " Line: " . $e->getLine() . PHP_EOL;}- Run the Script:
# Run the SPL exceptions demonstrationphp spl-exceptions.phpExpected Result
Section titled “Expected Result”5 / 2 = 2.5Invalid argument: Denominator cannot be zero.Factorial of 5: 120Error: Number too large. Maximum supported value is 20.Exception Details: Message: Denominator cannot be zero. Code: 0 File: /path/to/spl-exceptions.php Line: 15Why It Works
Section titled “Why It Works”Common SPL Exception Types:
InvalidArgumentException: When a function receives an argument of incorrect type or invalid valueOutOfRangeException: When a value is not within an expected rangeOutOfBoundsException: For array/collection access beyond valid boundsRuntimeException: For errors that can only be detected at runtimeLogicException: For errors in program logic (should never happen in production)UnexpectedValueException: When a function returns an unexpected value type
Multi-catch syntax (PHP 7.1+) lets you handle multiple exception types in one catch block using the pipe (|) operator.
Exception Object Methods:
getMessage(): The error messagegetCode(): Numeric error code (default 0)getFile(): File where exception was throwngetLine(): Line number where exception was throwngetTrace(): Array representation of stack tracegetTraceAsString(): String representation of stack trace
Troubleshooting
Section titled “Troubleshooting”Problem: “Class ‘InvalidArgumentException’ not found” error.
Solution: SPL exceptions are built-in to PHP 5.1+. If you see this error, check your PHP installation.
Problem: “Syntax error” on the multi-catch line.
Solution: Multi-catch syntax requires PHP 7.1 or later. Update your PHP version or use separate catch blocks.
::: tip
Always use the most specific exception type that matches your use case. InvalidArgumentException is clearer than generic Exception, making debugging easier and code more maintainable.
:::
Step 6: Exception Chaining and Error Types (~4 min)
Section titled “Step 6: Exception Chaining and Error Types (~4 min)”When catching and re-throwing exceptions, you can preserve the original exception context using exception chaining. Additionally, PHP 7+ distinguishes between Error and Exception classes.
Understand exception chaining for debugging and the difference between Error and Exception.
Actions
Section titled “Actions”- Create a New File:
Create
exception-chaining.php:
<?phpdeclare(strict_types=1);
/** * Demonstrates exception chaining and Error vs Exception */
class UserService{ public function loadUser(int $userId): array { try { // Simulate a database error throw new RuntimeException("Database connection failed"); } catch (RuntimeException $e) { // Re-throw with more context, preserving original exception throw new Exception( "Failed to load user with ID: $userId", 0, $e // The previous exception is preserved ); } }}
// Example 1: Exception chainingecho "=== Exception Chaining ===" . PHP_EOL;try { $service = new UserService(); $user = $service->loadUser(123);} catch (Exception $e) { echo "Current exception: " . $e->getMessage() . PHP_EOL;
// Access the previous exception in the chain if ($previous = $e->getPrevious()) { echo "Original cause: " . $previous->getMessage() . PHP_EOL; }}
// Example 2: Error vs Exception (PHP 7+)echo PHP_EOL . "=== Error vs Exception ===" . PHP_EOL;
// This will trigger a TypeError (Error, not Exception)try { function requireString(string $value): void { echo "Received: $value" . PHP_EOL; }
// Uncommenting this line would cause a TypeError in strict mode // requireString(123); // Type error: expected string, got int
// Instead, demonstrate catching both Error and Exception throw new TypeError("Expected string, got integer");
} catch (TypeError $e) { echo "Type error caught: " . $e->getMessage() . PHP_EOL;} catch (Throwable $e) { // Throwable is the parent interface for both Error and Exception echo "Caught throwable: " . $e->getMessage() . PHP_EOL;}
echo PHP_EOL . "Script completed successfully." . PHP_EOL;- Run the Script:
# Run the exception chaining demonstrationphp exception-chaining.phpExpected Result
Section titled “Expected Result”=== Exception Chaining ===Current exception: Failed to load user with ID: 123Original cause: Database connection failed
=== Error vs Exception ===Type error caught: Expected string, got integer
Script completed successfully.Why It Works
Section titled “Why It Works”Exception Chaining preserves the original error context when wrapping exceptions in higher-level exceptions. The third parameter of the Exception constructor accepts a previous exception, creating a chain you can traverse with getPrevious().
Error vs Exception (PHP 7+):
Errorclass: For internal PHP errors (type errors, parse errors, etc.)Exceptionclass: For application-level exceptions- Both implement
Throwableinterface (the root of all throwable objects) - You can catch both with
catch (Throwable $e)
Common Error types:
TypeError: Type declaration violationsParseError: Syntax errors in eval() or requireArgumentCountError: Wrong number of arguments to a functionDivisionByZeroError: Division or modulo by zeroArithmeticError: Math operation errors
::: warning
Never catch Throwable or Error unless you have a specific reason (like logging). These represent serious problems that usually shouldn’t be recovered from. Stick to catching Exception and its subclasses for application logic.
:::
Troubleshooting
Section titled “Troubleshooting”Problem: getPrevious() returns null.
Solution: Ensure you’re passing the previous exception as the third parameter when throwing: throw new Exception($message, $code, $previousException).
Problem: “Class ‘TypeError’ not found” error.
Solution: TypeError was introduced in PHP 7.0. Ensure you’re using PHP 7.0 or later.
Best Practices
Section titled “Best Practices”Before moving on, here are some key principles for professional exception handling:
When to Use Exceptions
Section titled “When to Use Exceptions”✅ Use exceptions for:
- Unexpected conditions (file not found, network timeout, invalid user input)
- Errors that prevent normal execution
- Validating preconditions (invalid arguments)
- Operations that fail in ways the caller should handle
❌ Don’t use exceptions for:
- Normal control flow (use return values instead)
- Expected conditions (use conditional checks)
- Performance-critical loops (exceptions are expensive)
- Situations where a return value would be clearer
Exception Naming Conventions
Section titled “Exception Naming Conventions”- Exception class names should end with
Exception:InvalidEmailException, notInvalidEmail - Be specific:
InsufficientFundsException>BankAccountException>Exception - Use SPL exceptions when they fit:
InvalidArgumentExceptioninstead of customBadArgumentException
Exception Message Guidelines
Section titled “Exception Message Guidelines”// ❌ Bad: Vague messagethrow new Exception("Error");
// ✅ Good: Specific, actionable messagethrow new InvalidArgumentException( "Email address must contain '@' symbol. Received: $email");Catching Exceptions
Section titled “Catching Exceptions”// ❌ Bad: Catching and ignoringtry { riskyOperation();} catch (Exception $e) { // Silent failure - never do this}
// ✅ Good: Catch specific types, log, and handle appropriatelytry { riskyOperation();} catch (InvalidArgumentException $e) { // Log the error error_log("Invalid argument: " . $e->getMessage()); // Inform the user echo "Please provide valid input.";} catch (RuntimeException $e) { error_log("Runtime error: " . $e->getMessage()); echo "An error occurred. Please try again later.";}Re-throwing Exceptions
Section titled “Re-throwing Exceptions”// ✅ Good: Preserve context when re-throwingcatch (DatabaseException $e) { throw new UserNotFoundException( "Could not find user with ID: $userId", 0, $e // Preserve original exception );}All code examples from this chapter are available in the repository:
/series/php-basics/code/11-exceptions.php– Basic exception handling/series/php-basics/code/11-finally-demo.php– Finally block demonstration/series/php-basics/code/11-bank-account.php– Custom exceptions/series/php-basics/code/11-spl-exceptions.php– SPL exception types and multi-catch/series/php-basics/code/11-exception-chaining.php– Exception chaining and Error vs Exception
Exercises
Section titled “Exercises”-
Array Access with SPL Exceptions (~10 min):
- Create a
ProductCatalogclass with a private array of products (e.g.,['laptop' => 999, 'mouse' => 25]). - Add a
getPrice(string $productName): floatmethod. - If the product doesn’t exist, throw an
OutOfBoundsExceptionwith a descriptive message. - If the product name is empty, throw an
InvalidArgumentException. - In your main code, use multi-catch syntax to handle both exception types in a single catch block.
- Bonus: Add a
setPrice(string $product, float $price)method that throwsOutOfRangeExceptionif the price is negative or greater than 10,000.
- Create a
-
Enhanced User Validation (~15 min):
- Create a custom
ValidationExceptionclass that extendsInvalidArgumentException(notException). - Create a
Userclass withsetEmail(string $email): voidandsetAge(int $age): voidmethods. - In
setEmail(), validate the email contains ’@’ and ’.’, otherwise throwValidationException. - In
setAge(), throwOutOfRangeExceptionif age is less than 13 or greater than 120. - Use constructor property promotion for storing the values.
- In your main code, catch
ValidationException,OutOfRangeException, and a genericExceptionin separate catch blocks. - Bonus: Add exception chaining—catch any exceptions in a wrapper method and re-throw with additional context while preserving the original exception.
- Create a custom
-
Exception Chaining with Data Processing (~15 min):
- Create a
DataProcessorclass with aprocessFile(string $filename): arraymethod. - Inside
processFile(), wrap file operations in a try-catch block. - If the file doesn’t exist, throw
RuntimeExceptionwith “File operation failed”. - Catch that exception and re-throw a new
Exceptionwith message “Failed to process file: $filename”, passing the original exception as the third parameter. - In your main code, catch the re-thrown exception and use
getPrevious()to display both the current and original error messages. - Use
getFile(),getLine(), andgetTraceAsString()to display detailed debugging information. - Bonus: Add a
finallyblock that logs “Cleanup completed” regardless of success or failure.
- Create a
-
Enhanced Bank Account (~20 min):
- Refactor the
BankAccountclass from Step 4 to use SPL exceptions:- Use
InvalidArgumentExceptioninstead of genericExceptionfor negative amounts - Keep
InsufficientFundsExceptionas a custom exception
- Use
- Add a
deposit(float $amount)method that validates the amount is positive - Add a
transfer(BankAccount $to, float $amount)method that:- Validates both accounts aren’t the same (throw
LogicException) - Calls
withdraw()from the source account (may throwInsufficientFundsException) - Calls
deposit()on the target account - If deposit fails, re-deposits to the source account (rollback)
- Validates both accounts aren’t the same (throw
- Use exception chaining when re-throwing to preserve context
- Demonstrate multi-catch syntax to handle different exception types
- Bonus: Add a
lockedproperty and anAccountLockedExceptionthat’s thrown if operations are attempted on a locked account.
- Refactor the
Wrap-up
Section titled “Wrap-up”Congratulations! You’ve just completed a comprehensive deep dive into error and exception handling in PHP. You now know how to build robust, production-ready applications that handle failures gracefully. You’ve learned:
Core Exception Handling:
- Use
try...catchblocks to handle exceptions gracefully - Throw exceptions when operations fail
- Use
finallyfor guaranteed cleanup operations - Create custom exception classes for domain-specific errors
Professional Techniques:
- Use SPL exception types (
InvalidArgumentException,OutOfRangeException, etc.) for more semantic code - Handle multiple exception types with multi-catch syntax (PHP 7.1+)
- Use exception chaining with
getPrevious()to preserve error context - Leverage exception object methods (
getFile(),getLine(),getTrace()) for debugging
Best Practices:
- Choose specific exception types over generic
Exception - Write clear, actionable exception messages
- Never silently catch and ignore exceptions
- Understand when to use exceptions vs return values
- Distinguish between
Error(PHP internal) andException(application-level)
Using these techniques, you control exactly what happens when things go wrong, preventing crashes and providing clear feedback to users. This is a critical skill for building production-ready applications that handle edge cases professionally.
What You Accomplished
Section titled “What You Accomplished”✅ Built a safe division function that handles edge cases
✅ Created a bank account system with custom exceptions
✅ Learned to use finally for cleanup operations
✅ Mastered the exception handling flow in PHP
✅ Used SPL exceptions for more semantic error handling
✅ Applied multi-catch syntax to handle multiple exception types
✅ Implemented exception chaining to preserve error context
✅ Learned professional exception handling best practices
Next Steps
Section titled “Next Steps”In Chapter 12: Dependency Management with Composer, you’ll learn how to use Composer, PHP’s package manager, to integrate third-party libraries into your projects and manage dependencies professionally. Exception handling becomes even more important when working with external packages that may throw their own exception types.
Knowledge Check
Section titled “Knowledge Check”Test your understanding of error and exception handling:
Further Reading
Section titled “Further Reading”- PHP Manual: Exceptions – Official documentation on exception handling
- PHP Manual: Predefined Exceptions – Complete list of built-in exception types
- PHP Manual: SPL Exceptions – Standard PHP Library exception types
- PHP Manual: Errors in PHP 7 – Understanding the Error hierarchy
- PSR-3: Logger Interface – Standard for logging exceptions in production
- PHP 8.0: Throw Expression – Modern exception features