PHP Exceptions

Handling errors gracefully with try-catch blocks

⚠️ What are Exceptions?

Exceptions are special objects that represent errors or unexpected conditions in your code. They allow you to handle errors gracefully using try-catch blocks instead of letting your application crash unexpectedly.


<?php
try {
    // Code that might throw an exception
    $result = 10 / 0;
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
// Output: Error: Division by zero
?>
                                    

Output:

Error: Division by zero

Exception Handling Concepts

🎯

Try Block

Contains code that might throw an exception. Execution stops at the first exception thrown.

<?php
try {
    // Risky code here
    $file = fopen("data.txt", "r");
}
?>
🛡️

Catch Block

Handles exceptions thrown in the try block. You can catch specific exception types.

<?php
catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
?>
🔄

Finally Block

Executes regardless of whether an exception was thrown, perfect for cleanup operations.

<?php
finally {
    // Always runs
    echo "Cleanup complete";
}
?>
🚀

Throw Statement

Manually throw exceptions when you detect error conditions in your code.

<?php
if ($age < 18) {
    throw new Exception("Too young");
}
?>

🔹 Basic Try-Catch

Catch and handle exceptions to prevent application crashes:

<?php
function divide($a, $b) {
    if ($b == 0) {
        throw new Exception("Cannot divide by zero!");
    }
    return $a / $b;
}

try {
    echo "10 / 2 = " . divide(10, 2) . "<br>";
    echo "10 / 0 = " . divide(10, 0) . "<br>";
    echo "This won't execute";
} catch (Exception $e) {
    echo "Caught exception: " . $e->getMessage();
}
?>

Output:

10 / 2 = 5
Caught exception: Cannot divide by zero!

🔹 Multiple Catch Blocks

Handle different exception types with separate catch blocks:

<?php
class InvalidAgeException extends Exception {}
class InvalidEmailException extends Exception {}

function validateUser($age, $email) {
    if ($age < 18) {
        throw new InvalidAgeException("Age must be 18 or older");
    }
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new InvalidEmailException("Invalid email format");
    }
    return "User is valid";
}

try {
    echo validateUser(15, "[email protected]");
} catch (InvalidAgeException $e) {
    echo "Age Error: " . $e->getMessage();
} catch (InvalidEmailException $e) {
    echo "Email Error: " . $e->getMessage();
} catch (Exception $e) {
    echo "General Error: " . $e->getMessage();
}
?>

Output:

Age Error: Age must be 18 or older

🔹 Finally Block

Code in finally always executes, even if an exception occurs:

<?php
function processFile($filename) {
    $file = null;
    try {
        echo "Opening file...<br>";
        $file = fopen($filename, "r");
        
        if (!$file) {
            throw new Exception("File not found");
        }
        
        echo "Processing file...<br>";
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage() . "<br>";
    } finally {
        echo "Cleanup: Closing resources<br>";
        if ($file) {
            fclose($file);
        }
    }
}

processFile("nonexistent.txt");
?>

Output:

Opening file...
Error: File not found
Cleanup: Closing resources

🔹 Custom Exception Classes

Create your own exception types for specific error scenarios:

<?php
class DatabaseException extends Exception {
    public function errorMessage() {
        return "Database Error on line {$this->getLine()}: {$this->getMessage()}";
    }
}

class ValidationException extends Exception {
    private $field;
    
    public function __construct($message, $field) {
        parent::__construct($message);
        $this->field = $field;
    }
    
    public function getField() {
        return $this->field;
    }
}

try {
    throw new ValidationException("Invalid input", "email");
} catch (ValidationException $e) {
    echo "Field '{$e->getField()}': {$e->getMessage()}";
}
?>

Output:

Field 'email': Invalid input

🔹 Exception Methods

Access useful information from exception objects:

<?php
try {
    throw new Exception("Something went wrong", 500);
} catch (Exception $e) {
    echo "Message: " . $e->getMessage() . "<br>";
    echo "Code: " . $e->getCode() . "<br>";
    echo "File: " . $e->getFile() . "<br>";
    echo "Line: " . $e->getLine() . "<br>";
    echo "Trace: " . $e->getTraceAsString();
}
?>

Output:

Message: Something went wrong
Code: 500
File: /path/to/file.php
Line: 3
Trace: #0 {main}

🔹 Re-throwing Exceptions

Catch an exception, do something, then throw it again:

<?php
function processData($data) {
    try {
        if (empty($data)) {
            throw new Exception("Data is empty");
        }
        // Process data...
    } catch (Exception $e) {
        // Log the error
        error_log($e->getMessage());
        // Re-throw for higher level handling
        throw $e;
    }
}

try {
    processData("");
} catch (Exception $e) {
    echo "Final handler: " . $e->getMessage();
}
?>

Output:

Final handler: Data is empty

🔹 Global Exception Handler

Set a default handler for uncaught exceptions:

<?php
// Set global exception handler
set_exception_handler(function($exception) {
    echo "Uncaught Exception: " . $exception->getMessage() . "<br>";
    echo "Please contact support.";
});

// This exception won't be caught
throw new Exception("Critical error occurred");

// Code after exception won't execute
echo "This won't display";
?>

Output:

Uncaught Exception: Critical error occurred
Please contact support.

🔹 Best Practices

Exception Handling Tips:

  • Be Specific - Catch specific exception types before general ones
  • Don't Catch Everything - Only catch exceptions you can handle
  • Use Finally - Clean up resources in finally blocks
  • Meaningful Messages - Provide clear error messages
  • Log Errors - Always log exceptions for debugging
  • Custom Exceptions - Create custom exception classes for your domain
  • Don't Hide Errors - Don't use empty catch blocks

Common Exception Types:

  • Exception - Base exception class
  • InvalidArgumentException - Invalid function arguments
  • RuntimeException - Errors during runtime
  • LogicException - Logic errors in code
  • PDOException - Database errors

🧠 Test Your Knowledge

Which block always executes, even if an exception occurs?