What are exceptions and how to handle them?
Exception handling is an elegant way to handle errors which are beyond the program’s scope.
In this tutorial, we are going to learn how and when to use exception handling and, even more important, when not to use it.
In order to explain the need for exception handling, we will try to see what happens when a program is fed with faulty data. In our example, we will develop the class FuelEconomy that calculates with the method calculate() the fuel efficiency of cars by dividing the distance traveled by the gas consumption.
1 2 3 4 5 6 7 |
class FuelEconomy { // Calculate the fuel efficiency public function calculate($distance, $gas) { return $distance/$gas; } } |
We will feed the class with the nested array $dataFromCars, in which each nested array has two values: the first value is for the distance traveled and the second value is for the gas consumption. While the first and last nested arrays contain legitimate data, the second nested array provides zero gas consumption and the third nested array has negative gas consumption.
1 2 3 4 5 6 |
$dataFromCars = array( array(50,10), array(50,0), array(50,-3), array(30,5) ); |
Here is what happens when we feed the array to the class:
1 2 3 4 5 |
foreach($dataFromCars as $data => $value) { $fuelEconomy = new FuelEconomy(); echo $fuelEconomy -> calculate($value[0],$value[1]) . "<br />"; } |
Result:
5
Warning: Division by zero
-16.666666666667
6
From the result, we can see what might happen when we feed the class with faulty data. On the second line, we got a nasty warning for trying to divide by zero while, on the third line, we got a negative value (which is not what we would expect for gas efficiency). These are the kinds of errors that we would like to suppress by using exception handling.
How to throw an exception?
When handling exceptions, we make use of the Exception class, which is a built-in PHP class. We throw the exception with the command throw new Exception() that creates the exception object. Between the brackets of the throw new Exception() command, we write our own custom message that we would like to appear in the case of the exception.
In the example given below, whenever the user tries to feed the class with a gas consumption value that is less than or equal to zero, a custom message is thrown instead of an error.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class FuelEconomy { // Calculate the fuel efficiency public function calculate($distance, $gas) { if($gas <= 0 ) { // Throw custom error message, instead of an error throw new Exception("The gas consumption cannot be less than or equal to zero. You better drink coffee or take a break."); } return $distance/$gas; } } |
If we run the code as it is written now, we’ll get an even nastier error because, in order to handle exceptions, we need to not just throw the exception but also to catch it.
How to catch an exception?
In order catch an exception, we need two blocks:
- A try block.
- A catch block.
While the try block runs the normal data, the faulty data is handled by the catch block. Inside the catch block, we use methods that the PHP Exception class provides.
In the example given below, the custom error message that we throw from the try block is being caught by the catch block that, in turn outputs the error message with the getMessage() method (which is a method that the Exception class provides).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class FuelEconomy { // Calculate the fuel efficiency public function calculate($distance, $gas) { if($gas <= 0 ) { // Throw custom error message, instead of an error throw new Exception("The gas consumption cannot be less than or equal to zero. You better drink coffee or take a break."); } return $distance/$gas; } } // The data to feed the class with $dataFromCars = array( array(50,10), array(50,0), array(50,-3), array(30,5) ); // Create the object from the class and feed it // with the array values foreach($dataFromCars as $data => $value) { // Try block handles the normal data try { $fuelEconomy = new FuelEconomy(); echo $fuelEconomy -> calculate($value[0],$value[1]) . "<br />"; } // Catch block handles the exceptions catch (Exception $e) { // Echo the custom error message echo "Message: " . $e -> getMessage() . "<br />"; } } |
Result:
5
Message: The gas consumption cannot be less than or equal to zero. You better drink coffee or take a break. Message: The gas consumption cannot be less than or equal to zero. You better drink coffee or take a break.
6
Thanks to exception handling, we now get an elegant error message instead of the nasty one that we got when not using exception handling.
Are there any other methods that can help us handle exceptions?
The Exception class is a PHP built-in class that offers several helpful methods. We have already used the getMessage() method to get a custom error message, yet there are other beneficial methods that the Exception class provides. Of those, the most beneficial are:
- getFile() that returns the path to the file in which the error occurred.
- getLine() that returns the line in which the exception occurred.
We can now use the getFile() and getLine() methods to add the path and line in which the exception has occurred to the custom message from the above example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
foreach($dataFromCars as $data => $value) { try { $fuelEconomy = new FuelEconomy(); echo $fuelEconomy -> calculate($value[0],$value[1]) . "<br />"; } catch (Exception $e) { echo "Message: " . $e -> getMessage() . "<br />"; // Output the path to the file echo "File: " . $e -> getFile() . "<br />"; // Output the line in the code echo "Line: " . $e -> getLine() . "<br />"; echo "<hr />"; } } |
Result:
5
Message: The gas consumption cannot be less than or equal to zero. You better drink coffee or take a break.
File: C:wampwwwindex.php
Line: 9
Message: The gas consumption cannot be less than or equal to zero. You better drink coffee or take a break.
File: C:wampwwwindex.php
Line: 9
6
The result above demonstrates that exception handling can provide more than custom messages. It can provide beneficial data for tracing the exceptions.
What about writing the exceptions to a log file?
In the same way that we can echo the exception messages to the user, we can also write them into a log file with the error_log() command. For example:
1 |
error_log($e -> getFile()); |
In our example, let’s now add the ability to write errors into the log file whenever an exception is thrown:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
foreach($dataFromCars as $data => $value) { try { $fuelEconomy = new FuelEconomy(); echo $fuelEconomy -> calculate($value[0],$value[1]) . "<br />"; } catch (Exception $e) { // Echo the error message to the user echo "Message: " . $e -> getMessage() . "<br />"; echo "<hr />"; // Write the error into a log file error_log($e -> getMessage()); error_log($e -> getFile()); error_log($e -> getLine()); } } |
When to use exception handling?
The sole purpose of exception handling is to handle external problems, such as math errors, logical errors, or technical difficulties.
Exception handling is a great tool that handles specific errors that are outside the scope of a program. These errors might be math errors, logical errors or technical difficulties, examples of which are as follows:
- Math errors, e.g., trying to divide by zero.
- Logical errors happen when trying to do something that doesn’t make sense in the context of the program (like assigning a negative value to gas consumption). •
- Technical problems are most often caused by hardware failure (like the computer running out of memory) but they can also be the fault of external services (like communication failures or problems with an external API).
It is important to stress that, although exception handling is a great tool for handling errors which are outside the scope of the program in an elegant way, it is not a way to hide bugs or badly written code. It is also not a fancy way to replace if-then and switch statements. The sole purpose of exception handling is to handle external problems, such as math errors, logical errors, or technical difficulties.]]>