Posts tagged ‘Errors’

PHP Error Handling

Previously I wrote about Exceptions as a way of dealing with error cases in PHP. Exceptions are a great way to anticipate errors and handle them appropriately. Unfortunately, however, it is not possible to anticipate every error and you users still might be presented with an ugly error message generated by PHP. One way to prevent users from seeing warnings or errors generated by PHP is to turn off error reporting. The down side to using this method is that you might not be aware that an error is occuring, and you’ll be even less aware of the details of that error.

A better solution would be to use a custom error handler. PHP provides you with a function that allows you to override the default error handler called set_error_handler. This function takes as input a callback, which is your custom error handling function. Once you call set_error_handler, PHP will no longer report errors as it normally would and instead pass those errors to your function. The function you define must take at least two inputs: error number, and error message, and optionally three additional parameters: error file, error line, and error context. I’ll go into more detail about this later, lets define our function:

set_error_handler('customHandler');

function customHandler($eNum, $eMsg, $eFile, $eLine, $eContext)
{
     switch(eNum)
     {
          case E_WARNING:
               echo "the following warning occured on line $eLine in $eFile: $eMsg";
               break;
          case E_NOTICE:
               echo "the following notice occured on line $eLine in $eFile: $eMsg";
               break;
          case E_ERROR:
               echo "the following error occured on line $eLine in $eFile: $eMsg";
               break;
     }
     return true;
}

In the above example we override the defualt error handler with our custom handler, customHandler. Anytime an error or warning occurs PHP will pass that error to our function. In this case, we use a switch statement to deal with each of our three error types: E_WARNING, E_NOTICE, and E_ERROR. Note that there are actually several more error types; you can find them Here.

Once the error has been passed to our function, we simply output the error message and the file and line number it occured in. This isn’t a whole lot different than the default behavior, but this code could easily be modified to create a database entry everytime an error occurs. Using this method, you could review all of the errors your users are getting as well as give them a customized error message. In the code above, I do not use the eContext parameter in my error reporting. eContext is an array containing of every variable at the time the error occured. Typically this is not something you show to a user, but can be very useful in debugging your program.

Note that the function we created returns true when it is complete. This is important. If it were to return false PHP would return control to the default error handler. If you wish to restore the default error handler you can use the restore_error_handler function.

Now that you know how to write a function that will override the default behavior when an error occurs, you might want to trigger your own errors that can be handled by this function. You can do this using the trigger_error function with an error message as the first parameter and optionally an error type as the second parameter. The defuault error type for trigger_error is E_USER_NOTICE, but it can also be set to E_USER_WARNING, or E_USER_ERROR. The method of triggering a user error and handling it with a custom error handler is similar to exception handling, though I would advice using this method only when reporting errors. If an error can be recovered from or there is an alternatice behavior that your program should use, exceptions are the way to go. If you want to present your user with custom error messages and track when errors occur, custom error handling is the way to go.

PHP Exception Handling

If you’ve ever coded in Java or C++ you probably know what exceptions are. If not, that’s okay. I’ll go over the basics.

Exceptions modify the control flow of a program. Usually, they are generated by functions when an error occurs. Throwing and catching exceptions allow the programmer to anticipate an error and handle it accordingly. For example: Say you write a function to open up a file and read its contents. When the function tries to open the file, however, it finds that the file does not exist. Generally this would just generate a nasty error and your program would terminate. If the programmer is aware that this is a possibility, however, he or she could check for that and throw an exception which would be caught and handled in a more user friendly fashion.

Enough talk lets see some code.

function open_file($fileName)
{
     if($contents = @file_get_contents($fileName))
          return $contents;
     else
          throw new Exception('Bad File Name!');
}

try
{
     $text = read_file('MyFile.txt');
}
catch(Exception $e)
{
     echo $e->getMessage();
}

In the code above, our function call, read_file, is surrounded by a try block which is followed by a catch block. The try block tells PHP that it should try to execute the code inside the block, while looking for the exception specified by the catch statement. The body of the catch statement tells PHP what to do in the event that exception is caught. In the case above if the file cannot be opened we simply echo ‘Bad File Name!’.

This example of course is trivial, but using exceptions you can better handle errors as they occur, which is bound to happen anytime user input is involved.

In the example above, a general exception is thrown. The exception itself is an object, the one above, has a constructor that takes as input a string. PHP, however, lets us define our own exceptions. Here’s how:

class CustomException extends Exception
{
     private $message;

     function __construct($message)
     {
          $this->message = $message;
     }

     function getMessage()
     {
          return $this->message;
     }
}

In the example above we define an exception called CustomException. Note that in the class declaration it states the CustomException extends Exception. In order for an exception to be thrown our custom exception class must extend Exception. A side effect of this is that if a function throws an exception within a try block, if the catch block is set to catch a general exception, it will catch ANY exception, including our CustomException. In the example, I create an exception class that is effectively identical to a general exception (though stripped down). You can however, define your exceptions in whatever way suits your needs.

It is important to remember when using exceptions, that if the exception occurs, code within the try block will stop executing. Be careful when putting code within a try block, only add code that cannot be executed if the exception occurs. For instance, if we call read_file, only code that needs the contents of that file should be inside the try block.