PHP Error Handling Creating Your Own Exception Classes - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript PHP Error Handling Creating Your Own Exception Classes - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Sunday, June 30, 2019

PHP Error Handling Creating Your Own Exception Classes

PHP Error Handling



Creating Your Own Exception Classes


Problem

You want control over how (or if) error messages are displayed to users, even though you’re using several third-party libraries that each have their own views on handling errors.

Solution

Take advantage of PHP 5’s support for exceptions to create your own exception handler that will do your bidding when errors occur in third-party libraries:

       class CustomException extends Exception {
              public function __construct($e) {
                     // make sure everything is assigned properly
                     parent::__construct($e->getMessage(), $e->getCode());

                     // log what we know
                     $msg = "------------------------------------------------\n";
                     $msg .= __CLASS__ . ": [{$this->code}]: {$this->message}\n";
                     $msg .= $e->getTraceAsString() . "\n";
                     error_log($msg);
              }
           
              // overload the __toString() method to suppress any "normal" output
              public function __toString() {
                     return $this->printMessage();
              }
       
              // map error codes to output messages or templates
              public function printMessage() {
  
                     $usermsg = '';
                     $code = $this->getCode();

                     switch ($code) {
                     case SOME_DEFINED_ERROR_CODE:

                            $usermsg = 'Ooops! Sorry about that.';
                            break;
                     case OTHER_DEFINED_ERROR_CODE:
                            $usermsg = "Drat!";
                            break;
                     default:
                            $usermsg = file_get_contents('/templates/general_error.html');
                            break;
                     }
                     return $usermsg;
              }

              // static exception_handler for default exception handling
              public static function exception_handler($exception) {
                     throw new CustomException($exception);
              }
       }

       // make sure to catch every exception
       set_exception_handler('CustomException::exception_handler');

       try {
              $obj = new CoolThirdPartyPackage();
       } catch (CustomException $e) {
              echo $e;
       }

Discussion

PHP 5 introduced the concept of exceptions to PHP. Exceptions are a common construct in many other languages; they’re used to deal gracefully with unforeseen error conditions. This is particularly useful when including third-party library code in your scripts when you’re not 100 percent confident how that code will behave in unpredictable circumstances, such as loss of database connectivity, an unresponsive remote API server, or similar acts of randomness.

Exceptions provide your scripts with a try/catch structure you use to create a sand‐boxed section of your script where things can go horribly wrong without hurting anything else:

       try {
              // do something
              $obj = new CoolThing();
       } catch (CustomException $e) {
              // at this point, the CoolThing wasn't cool
              print $e;
       }

So why use a custom exception, when PHP 5 already provides a perfectly functional exception class? The default exception class doesn’t exactly fulfill the graceful part of handling unpredictable results. It just prints out an error message not much different from regular errors. If you want truly flexible handling of these unfortunate events, a custom exception handler allows you to do what you have determined is the most appropriate given the condition.

In the CustomException class in the preceding code, you have two objectives. The first is to log everything you can about what happened; the second is to be as cool as possible from the user’s perspective.

The __construct() method sets up the exception by calling the parent’s constructor (the constructor of the default exception class) to ensure that all possible values are set for use by your custom exception’s methods.

Then, you immediately log what you can, using an error_log() call that you can replace with a custom error logger of your choice. In keeping with the goal of handling this error gracefully, make sure that your error logger is capable of logging this error without causing another one. For example, if the error you’re about to log is related to failed database connectivity, it’s probably a good idea if you don’t try to log this error to an error log table on that same database server.

From there, the CustomException class is written to expect the calling code to print out the error. However, that is not required behavior. You could just as easily have a try/catch block like this:

       try {
              // do something
              $obj = new CoolThing();
       } catch (CustomException $e) {
              // at this point, the CoolThing wasn't cool
              $e->redirectToOhNoPage();
       }

The segment catch (CustomException $e) means that an instance of the CustomException class will be instantiated and assigned to the variable $e. From there, $e is just an object that has some predefined values and methods relating to the problem that caused the exception, but is otherwise a regular object that can be as simple or as complicated as you want it to be.

One primary difference between a standard error handler and exceptions is the concept of recovery. The use case shown in this recipe thus far has a good correlation with the set_error_handler() usage you may already be familiar with. The idea is that your custom handler can contain a clean-up routine that checks the state of the application at the time that the custom exception is caught, cleans up as best as it can, and dies gracefully

Exceptions can also be used to easily recover from an error in the midst of an application’s flow. For example, a try block can have multiple catch blocks that are somewhat neater than a bunch of if/else/else/else blocks:

       try {
              // do something
              $obj = new CoolThing();
       } catch (PossibleException $e) {
              // we thought this could possibly happen
              print "<!-- caught exception $e! -->";
              $obj = new PlanB();
       } catch (AnotherPossibleException $e) {
              // we knew about this possibility as well
              print "<!-- aha! caught exception $e -->";
              $obj = new PlanC();
       } catch (CustomException $e) {
               // if all else fails, go to clean-up
               $e->cleanUp();
               $e->bailOut();
       }

In this example, we’re able to use the try/catch structure to check for exception conditions without stepping out of the flow of this chunk of code, unless all else truly fails.If we were unable to recover in any of the ways we knew how to in line with the flow of the application, we still have the option of bailing out to a catchall custom exception.We can even throw a new exception inside the catch blocks in order to influence the order in which exceptions bubble up to a try/catch block that may be wrapping the chunk of code currently executing.


No comments:

Post a Comment

Post Top Ad