Error Handling & Exceptions in PHP

Modern versions of PHP support error handling through the use of exceptions. PHP has several different predefined types of exceptions and also allows you to define your own exception types by creating new classes that inherit from the generic Exception class. PHP uses the standard try-catch-finally control structure to handle exceptions and allows you to throw your own exceptions.

Throwing Exceptions

Though PHP defines several different types of exceptions, we’ll only cover the generic Exception class. We can throw an exception in PHP by using the keyword throw and creating a new Exception with an error message.

throw new Exception("Something went wrong");

By using a generic Exception , we can only attach a message to the exception (which can be printed by code that catches the exception). If we want more fine-grained control over the type of exceptions, we need to define our own exceptions.

Catching Exceptions

To catch an exception in PHP you can use the standard try-catch control block. Optionally (and as of PHP version 5.5.0) you can use the finally block to clean up any resources or execute code regardless of whether or not an exception was raised. Consider the simple task of reading input from a user and manually parsing its value into an integer. If the user enters a non-numeric value, parsing will fail and we should instead throw an exception. Consider the following function:

function readNumber() {
  $input = readline("Please enter a number: ");
  if (is_numeric($input)) {
    $value = floatval($input);
  } else {
    throw new Exception("Invalid input!");
  }
}

Elsewhere in the code, we can surround a call to readNumber() in a try-catch statement:

try {
  readNumber();
} catch (Exception $e) {
  printf("Error: exception encountered: ".$e -> getMessage());
  exit(1);
}

In this example, we’ve simply displayed an error message to the standard output and exited the program. We’ve made the design decision that this error should be fatal. We could have chosen to handle this error differently in the catch block. The $e->getMessage() prints the message that the exception was created with. In this case, "Invalid input!".

Creating Custom Exceptions

As of PHP 5.3.0 it is possible to define custom exceptions by extending the Exception class. To do this, you need to declare a new class. (We’ll cover classes and objects in another chapter.) For now, we present a simple example. Consider the example in the previous chapter of computing the roots of a quadratic polynomial. One possible error situation is when the roots are complex numbers. We could define a new PHP exception class as follows:

/**
* Defines a ComplexRoot exception class
*/
class ComplexRootException extends Exception {
  public
  function __construct($message = null,
    $code = 0,
    Exception $previous = null) {
    // call the parent constructor
    parent::__construct($message, $code, $previous);
  }

  // custom string representation of object
  public
  function __toString() {
    return __CLASS__.
    ": [{$this->code}]: {$this->message}\n";
  }
}

Now in our code we can catch and even throw this new type of exception:

if( $b*$b - 4*$a*$c < 0) {
  throw new ComplexRootException("Cannot Handle complex roots");
}

Multiple Catch Blocks

 try {
   $r1 = getRoot($a, $b, $c);
 } catch (ComplexRootException $e) {
   //handle here
 } catch (Exception $e) {
   //handle all other types of exceptions here
 }

Review the code above. In it, we have two catch blocks. Since we can have multiple types of exceptions, we can catch each different type and handle them differently if we choose. Each catch block catches a different type of exception. The last catch block was written to catch a generic Exception. Much like an if-else-if statement, the first type of exception that is caught is the block that will be executed and they are all mutually exclusive. Thus, a generic “catch all” block like this should always be the last catch block. The most specific types of exceptions should be caught first and the most general types should be caught last.


Licenses and Attributions


Speak Your Mind

-->