Home arrow PHP arrow Page 5 - Error Handling in PHP: Introducing Exceptions in PHP 5

Exception subclassing: extending the functionality of the built-in Exception class - PHP

Welcome to the last part of the series “Error Handling in PHP.” In two parts, this series introduces the basics of error handling in PHP. It demonstrates some of the most common methods for manipulating errors in PHP 4, and explains the implementation of exceptions in PHP 5, particularly in object-oriented environments.

TABLE OF CONTENTS:
  1. Error Handling in PHP: Introducing Exceptions in PHP 5
  2. The basics of exceptions: using the “throw” statement and “try-catch” blocks
  3. Obtaining detailed error information: using built-in Exception class’ additional methods
  4. Working with error types: developing an improved error handling mechanism
  5. Exception subclassing: extending the functionality of the built-in Exception class
By: Alejandro Gervasio
Rating: starstarstarstarstar / 43
January 18, 2006

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

There are situations where the default functionality provided by the built-in Exception class is simply not enough. In these cases, the quickest way to resolve this issue is to extend the class itself, as done regularly with user-defined classes, and derive one or more child classes that handle specific errors. Considering this particular situation, I’ll show you how to implement exception subclassing, by defining a basic “CustomException” class, which can handle all the errors raised by the already familiar “FileReader” class. Have a look at the example below:

class FileReader{
  private $file;
  private $fileDir='fileDir/';
  const FILE_DATA_ERROR=1;
  const EMAIL_DATA_ERROR=2;
  public function __construct($file){
    if(!file_exists("{$this->fileDir}{$file}.php")){
      throw new CustomException('File '.$file.' not
found',self::FILE_DATA_ERROR);
    }
    $this->file=$file;
  }
  public function getContent(){
    if(!$content=file_get_contents("{$this->fileDir}{$this-
>file}.php")){
      throw new CustomException('Unable to read file
contents',self::FILE_DATA_ERROR);
    }
    return $content;
  }
  public function mailContent(){
    if(!@mail('Recipient<user@domain.com>','HTML Page',$this-
>getContent())){
      throw new CustomException('Unable to send by email file contents',self::EMAIL_DATA_ERROR);
    }
  }
}

As you can see, the sample class remains nearly the same. The only differences worth noticing here point to how exceptions are thrown by the class. Note that each time a failure occurs, a “CustomException” is triggered. This exception accepts an error message together with the appropriate error number as parameters. Of course, the instantiation of “CustomException” objects imply the existence of a class. Thus, here is the pertinent definition:

class CustomException extends Exception{
  public function logError(){
    // Send notification through the server log
    if($this->getCode()==FileReader::FILE_DATA_ERROR){
      error_log($this->getMessage(),0);
    }
    // Notify administrator by email
    else if($this->getCode()==FileReader::EMAIL_DATA_ERROR){
      error_log($this->getMessage(),1,'sysadmin@domain.com');
    }
  }
}

In simple terms, what I’ve done above is derive a child class from the original Exception class, so it’s possible to handle errors directly by the internals of the class, rather than within the “catch” block. Notice how the child class determines the course of action to be taken, based on the error number passed to the class constructor (in this case, the constructor of the Exception class hasn’t been overridden).

With reference to the above example, if a custom exception was thrown when reading file contents, the child class will store the error message in the system logger. Otherwise, if the error was raised when trying to send file data by email, then the error message is sent by email to the system administrator.

Since now all the processing of errors is handled behind the scenes by the “CustomException” class, the snippet to instantiate a “FileReader” object would be reduced to this:

try{
  $fr=new FileReader('sample_file');
  // email file content
  $fr->mailContent(); // potential error condition
  // echo file content
  echo $fr->getContent(); // potential error condition
}
catch(CustomException $e){
  $e->logError();
}

Definitely, the above script is now much simpler to code and read, due to the fact that all the exceptions are handled by the “logError()” method, defined earlier. Although the customized exception class is basic in its conception, it’s a useful example aimed at showing in a friendly way how to use Inheritance for deriving child exception handling classes.

Having developed a basic child class which is useful for illustrating exception subclassing in PHP 5, the last hands-on example of this tutorial will be focused on the development of two independent child classes, which break the whole exception handling process into two separated structures. For this reason, I’ll rewrite the sample “FileReader” class, like this:

class FileReader{
  private $file;
  private $fileDir='fileDir/';
  public function __construct($file){
    if(!file_exists("{$this->fileDir}{$file}.php")){
      throw new FileException('File '.$file.' not found');
    }
    $this->file=$file;
  }
  public function getContent(){
    if(!$content=file_get_contents("{$this->fileDir}{$this-
>file}.php")){
      throw new FileException('Unable to read file contents');
    }
    return $content;
  }
  public function mailContent(){
    if(!mail('Recipient<user@domain.com>','HTML Page',$this-
>getContent())){
      throw new MailException('Unable to send by email file
contents');
    }
  }
}

As shown above, the “FileReader” class now throws two different exceptions. The first one, “FileException,” is triggered when an error occurs when working with the sample file, while the second one, “MailException” is thrown when trying to send file data by email. Even when this level of detail can sometimes be unnecessary, it allows you to implement exception subclassing as deep as needed.

Returning to the previous example, below is the definition for the two corresponding child classes:

class FileException extends Exception{
  public function showError(){
    die($this->getMessage());
  }
}
// MailException extends Exception
class MailException extends Exception{
  public function logError(){
    error_log($this->getMessage(),1,'sysadmin@domain.com');
  }
}

As one would usually do with regular classes, I’ve derived both child classes from the parent Exception class, and provided specific functionality for each of them. The first one simply stops program execution after displaying the appropriate error message by using the “showError()” method, while the second one attempts to notify the system administrator by email, by utilizing the “logError()” method. Now, turn your attention to the following snippet of code, which demonstrates how to use these custom exception classes:

try{
  $fr=new FileReader('sample_file');
  // email file content
  $fr->mailContent(); // potential error condition
  // echo file content
  echo $fr->getContent(); // potential error condition
}
// catch FileException
catch(FileException $e){
  $e->showError();
}
// catch MailException
catch(MailException $e){
  $e->logError();
}

In this case, I’ve used two different “catch” blocks for trapping each custom exception and moving program flow to the corresponding block. As I said before, it’s possible to implement the required logic within each child class, in order to handle specific errors according to their nature and context.

As you can see, there is a lot of room for developing robust error handlers through exceptions, and certainly their level of complexity will be mostly dictated by the specific requirements of the web application that you’re going to develop. Once you’ve grasped the core concepts, learning to use exceptions within your PHP 5 applications can be a didactical experience.

Closing time

Finally we’re done. Over this two-part series, I’ve explored the basics of error handling in PHP. I covered rudimentary methods, mostly based on the usage of “die()” statements, and more powerful combinations, such as “trigger_error()/set_error_handler().” Also, I’ve taken a quick look at the popular PEAR_Error object, in order to implement error handling mechanisms in object-based environments. Of course, the last tutorial of the series has been focused entirely on explaining exceptions in PHP 5, and hopefully demonstrating their vast benefits to object-oriented programming.

Now that you know the basics of error handling in PHP, you can leap forward and start coding your applications defensively. Certainly, it’s something that your customers and your development team are going to thank you for in the future. See you in the next tutorial!



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: