PHP Exception Handling

What is an Exception

An exception is a signal that indicates an unusual event or error has occurred. Exceptions can arise from various situations, such as a failed database connection or query, or attempting to access a non-existent file.

PHP includes a robust exception handling mechanism that allows for graceful error management. Unlike PHP's traditional error handling system, exception handling is an object-oriented approach to error management, offering more controlled and flexible error reporting. The exception model was introduced in PHP 5.

Using Throw and Try...Catch Statements

In exception handling, code is enclosed within a try block. An exception can be thrown using the throw statement when an unexpected event occurs during the execution of code within the try block. This exception is then caught and handled by one or more catch blocks.

The following example illustrates how exception handling functions:

Example

Download
<?php
function division($dividend, $divisor){
// Throw exception if divisor is zero
if($divisor == 0){
throw new Exception('Division by zero.');
} else{
$quotient = $dividend / $divisor;
echo "<p>$dividend / $divisor = $quotient</p>";
}
}

try{
division(10, 2);
division(30, -4);
division(15, 0);

// If exception is thrown following line won't execute
echo '<p>All divisions performed successfully.</p>';
} catch(Exception $e){
// Handle the exception
echo "<p>Caught exception: " . $e->getMessage() . "</p>";
}

// Continue execution
echo "<p>Hello World!</p>";
?>

You may be curious about the purpose of this code. Let's break down each part of this code step by step for better understanding.

Explanation of Code

PHP's exception handling system consists primarily of four components: try, throw, catch, and the Exception class. The following list explains the functionality of each part:

  • The division() function in the example above checks if the divisor is zero. If it is, PHP throws an exception using the throw statement. Otherwise, the function performs the division using the provided numbers and displays the result.
  • Subsequently, the division() function is invoked within a try block with different arguments. If an exception occurs during the execution of code inside the try block, PHP halts execution and attempts to locate the corresponding catch block. If found, the code within that catch block is executed; otherwise, a fatal error occurs.
  • The catch block typically catches the exception thrown within the try block and creates an object ($e) containing information about the exception. The error message from this object can be retrieved using the Exception's getMessage() method.

PHP's Exception class also provides additional methods like getCode(), getFile(), getLine(), and getTraceAsString() for generating detailed debugging information.

Example

Download
<?php
// Turn off default error reporting
error_reporting(0);

try{
$file = "somefile.txt";

// Attempt to open the file
$handle = fopen($file, "r");
if(!$handle){
throw new Exception("Cannot open the file!", 5);
}

// Attempt to read the file contents
$content = fread($handle, filesize($file));
if(!$content){
throw new Exception("Could not read file!", 10);
}

// Closing the file handle
fclose($handle);

// Display file contents
echo $content;
} catch(Exception $e){
echo "<h3>Caught Exception!</h3>";
echo "<p>Error message: " . $e->getMessage() . "</p>";    
echo "<p>File: " . $e->getFile() . "</p>";
echo "<p>Line: " . $e->getLine() . "</p>";
echo "<p>Error code: " . $e->getCode() . "</p>";
echo "<p>Trace: " . $e->getTraceAsString() . "</p>";
}
?>

The Exception's constructor can accept an exception message and an exception code as optional parameters. The exception message is usually used to provide a general description of the error that occurred, while the exception code can categorize different types of errors. Later on, you can retrieve the provided exception code using the Exception's getCode() method.

Tip: Exceptions are meant to indicate unusual or exceptional situations in your code, such as errors or unexpected conditions. They should not be used for controlling regular application flow, like jumping to another part of the script at a specific point. Misusing exceptions in this way can negatively impact your application's performance.


Creating Custom Exceptions

You can also create your own custom exception handlers to handle different types of exceptions uniquely. This allows you to use separate catch blocks for each type of exception.

To define a custom exception, you extend the base Exception class, which is the foundation for all exceptions in PHP. By extending Exception, your custom exception inherits all the properties and methods of PHP's Exception class. Additionally, you can include your own custom methods within the custom exception class. Here's an example:

Example

Download
<?php
// Extending the Exception class
class EmptyEmailException extends Exception {}
class InvalidEmailException extends Exception {}

$email = "someuser@example..com";

try{
// Throw exception if email is empty
if($email == ""){
throw new EmptyEmailException("<p>Please enter your E-mail address!</p>");
}

// Throw exception if email is not valid
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {           
throw new InvalidEmailException("<p><b>$email</b> is not a valid E-mail address!</p>");
}

// Display success message if email is valid
echo "<p>SUCCESS: Email validation successful.</p>";
} catch(EmptyEmailException $e){
echo $e->getMessage();
} catch(InvalidEmailException $e){
echo $e->getMessage();
}
?>

In the example above, we've defined two new exception classes: EmptyEmailException and InvalidEmailException, both derived from the base Exception class. Multiple catch blocks are utilized to handle different error scenarios based on the type of exception thrown.

Since these custom exception classes inherit properties and methods from the Exception class, we can use methods like getMessage(), getLine(), getFile(), etc., to retrieve error details from the exception object.


Implementing a Global Exception Handler

As mentioned earlier, when an exception isn't caught, PHP generates a Fatal Error with an "Uncaught Exception ..." message, potentially exposing sensitive information like file names and line numbers to users. To avoid exposing such details, you can create a custom function and register it using the set_exception_handler() function to manage all uncaught exceptions.

Example

Download
<?php
function handleUncaughtException($e){
// Display generic error message to the user
echo "Opps! Something went wrong. Please try again, or contact us if the problem persists.";

// Construct the error string
$error = "Uncaught Exception: " . $message = date("Y-m-d H:i:s - ");
$error .= $e->getMessage() . " in file " . $e->getFile() . " on line " . $e->getLine() . "\n";

// Log details of error in a file
error_log($error, 3, "var/log/exceptionLog.log");
}

// Register custom exception handler
set_exception_handler("handleUncaughtException");

// Throw an exception
throw new Exception("Testing Exception!");
?>

Note: An uncaught exception always leads to script termination. To ensure continued script execution beyond the point where an exception occurs, you must include at least one corresponding catch block for each try block.