Intercepting Customized Exceptions in PHP 5

Welcome to the second part of a four-part series on sub classing exceptions in PHP 5. In the first part of this series, you learned how to build a basic processing class which could throw customized exceptions to client code. What you haven’t yet learned, however, is how to build the code to catch these exceptions. That is the topic of this article.

Introduction

As you probably know, one of the most relevant improvements incorporated into the object model of PHP 5 is the capacity for triggering and intercepting exceptions by way of conventional “try-catch” blocks. This feature facilitates the handling of different error conditions via a compact, highly-centralized mechanism.

While the built-in exception system that comes bundled natively with PHP 5 is usually good enough to handle errors and other critical conditions during the execution of a given web application, it’s worthwhile to mention that there are a number of additional cases where it is necessary to implement an exceptions system that can handle different failures in a more specific way.

That’s precisely where exception subclasses come in. It’s possible to derive a few different child classes from the base “Exception” built-in class, which allows us to build specific exception handling modules within a single PHP 5-driven application.

Of course, if you already read the introductory article of this series, then hopefully you’ll be familiar with building classes that are capable of triggering customized exceptions in the context of a concrete PHP 5 application. As you’ll certainly recall, in the course of that tutorial, I demonstrated how to define a basic MySQL-processing class which could throw MySQL-related exceptions to client code, instead of using only generic ones.

Indeed, building a class like the one described above is a straightforward process that doesn’t require you to have the sharpest skills for using the object-oriented parading with PHP 5. This only gives us half of the picture, however, since it’s also necessary to implement an exception mechanism that is capable of catching these customized, MySQL-related exceptions via a conventional “try-catch” block.

The mechanism in question can be quickly constructed by deriving a subclass from the parent “Exception” that comes included with PHP 5. Therefore, in the next few lines I’m going to teach you how perform this process in an approachable fashion, so you can start incorporating exception sub classes into your own PHP 5 applications in very short time. Let’s begin now!

{mospagebreak title=Triggering customized exceptions in PHP 5}

As I stated in the introduction, building a customized exception mechanism with PHP 5 involves two basic steps. First, we must define one or more classes that have the ability to trigger several specific exceptions when something goes wrong. Second, we need to derive the corresponding subclasses from the built-in “Exception” class, which must catch all of these exceptions.

As I mentioned before, in the preceding tutorial I showed you how to take the first step; I defined a MySQL-processing class, which was provided with the capacity for launching a few MySQL-related exceptions.

If the signature of this particular class doesn’t ring any bells for you, here it is:


// define ‘MySQL’ class

class MySQL{

private $conId;

private $host;

private $user;

private $password;

private $database;

private $result;

const OPTIONS=4;

public function __construct($options=array()){

if(count($options)!=self::OPTIONS){

throw new MySQLException(‘Invalid number of connection parameters’);

}

foreach($options as $parameter=>$value){

if(!$value){

throw new MySQLException(‘Invalid parameter ‘.$parameter);

}

$this->{$parameter}=$value;

}

$this->connectDB();

}

// connect to MySQL

private function connectDB(){

if(!$this->conId=mysql_connect($this->host,$this->user,$this->password)){

throw new MySQLException(‘Error connecting to the server’);

}

if(!mysql_select_db($this->database,$this->conId)){

throw new MySQLException(‘Error selecting database’);

}

}

// run query

public function query($query){

if(!$this->result=mysql_query($query,$this->conId)){

throw new MySQLException(‘Error performing query ‘.$query);

}

return new Result($this,$this->result);

}

}


// define ‘Result’ class

class Result {

private $mysql;

private $result;

public function __construct($mysql,$result){

$this->mysql=$mysql;

$this->result=$result;

}

// fetch row

public function fetchRow(){

if(!$row=mysql_fetch_assoc($this->result)){

return false;

}

return $row;

}

// count rows

public function countRows(){

if(!$rows=mysql_num_rows($this->result)){

throw new Exception(‘Error counting rows’);

}

return $rows;

}

// count affected rows

public function countAffectedRows(){

if(!$rows=mysql_affected_rows($this->mysql->conId)){

throw new Exception(‘Error counting affected rows’);

}

return $rows;

}

// get ID of last-inserted row

public function getInsertID(){

if(!$id=mysql_insert_id($this->mysql->conId)){

throw new Exception(‘Error getting ID’);

}

return $id;

 }

// seek row

public function seekRow($row=0){

if(!is_int($row)||$row<0){

throw new Exception(‘Invalid result set offset’);

}

if(!mysql_data_seek($this->result,$row)){

throw new Exception(‘Error seeking data’);

}

}

}


As you can see, the previous “MySQL” abstraction class will throw some exceptions of type “MySQLException” when failing to connect to the server and selecting a specific database, or when running a SQL query.

So far, the way this sample class has been defined is fairly understandable to you, right? The next thing I’m going to teach you will be how to create a customized exception class, whose task will be to catch the aforementioned MySQL-related exceptions.

The full details of how this will be done will be covered in the next section, so click on the link below to keep reading.

{mospagebreak title=Deriving a subclass from the built-in Exception class}

In the course of the previous section you hopefully learned how to build a basic MySQL abstraction class that is capable of throwing some customized exceptions of type “MySQLException” to client code. The next step we will take, then, consists of deriving a subclass from the base “Exception” class included with PHP 5. This subclass will be responsible for handling the aforementioned customized MySQL exceptions.

That being explained, please take a look at the following sample code. It  demonstrates how to build a specific exception class by using raw inheritance. Here it is:

// extend the built-in exception class to throw MySQL-related exceptions

class MySQLException extends Exception{

public function __construct($message,$code=0){

// call parent of Exception class

parent::__construct($message,$code);

}

public function showExceptionInfo(){

return ‘Catching MySQL exceptions…<br />Exception message: ‘.$this->getMessage().'<br />Source filename of exception: ‘.$this->getFile().'<br />Source line of exception: ‘.$this->getLine();

}

}


As you can see, things are becoming really interesting. In the above example, I simply derived a subclass from the native “Exception” parent available in PHP 5, in order to intercept all of the exceptions of type “MySQLException.”

In this particular case, this child class defines and implements a brand new method called “ShowExceptionInfo(),” which is admittedly fairly basic. However, it really comes in handy for demonstrating how to extend the functionality of the native exception mechanism offered by PHP 5, by the basic means of inheritance. Pretty simple to grasp, right?

So far, so good. At this stage you hopefully learned how to build a customized class that has the ability for handling exceptions other than the generic ones provided natively by PHP 5. Thus, in summary, on one hand I built a MySQL abstraction class that’s capable of triggering a few custom exceptions of type “MySQLException” to client code, while on the other hand there’s a specific class whose task is to handle these specific exceptions.

Undoubtedly, at this point you must be wondering how these two independent classes can be linked with each other in a useful fashion. And the answer is very simple, actually: by way of a simple “try-catch()” block! As you can see, it’s extremely easy to build a custom exception mechanism with PHP 5 by simply extending the functionality of its base “Exception” class with inheritance.

Nonetheless, I’m pretty sure that you’ll grasp how the “MySQLException” sub class does its thing much more easily if I show you an illustrative hands-on example. Bearing in mind this idea, in the section to come I’m going to built this concrete example for you, so you can learn very quickly how to implement a custom exception mechanism with PHP 5.

Go ahead and read the next few lines. I’ll be there, waiting for you.

{mospagebreak title=Intercepting some MySQL-related exceptions}

In the prior section, you hopefully learned how to derive a basic subclass from the built-in “Exception” class bundled with PHP 5 to create a customized exception mechanism that permits you to intercept all of the exceptions triggered by the sample “MySQL” class defined previously.

So now it’s time to set up an example to demonstrate the real functionality of the exception mechanism. Please study the following code sample, which shows how to handle generic and MySQL-related exceptions by using a couple of “catch()” blocks. Here it is:

try{

// connect to MySQL

$db=new MySQL(array(‘host’=>’host’,’user’=>’user’,’password’=>’password’,’database’=>’database’));

// fetch data on some users

$result=$db->query(‘SELECT * FROM users’);

// display data on some users

while($row=$result->fetchRow()){

echo ‘First Name: ‘.$row['firstname'].’ Last Name: ‘.$row['lastname'].’ Email: ‘.$row['email'].'<br />';

}

// turn off MySQL (throws a MySQL exception)

 

/* displays the following

Catching MySQL exceptions…

Exception message: Error connecting to the server

Source filename of exception: path/to/file/exception_test.php

Source line of exception: 36

*/

}

// catch MySQL exceptions here

catch(MySQLException $e){

echo $e->showExceptionInfo();

exit();

}

// catch default exceptions here

catch(Exception $e){

echo ‘Catching default exceptions…<br />';

echo ‘Exception message: ‘.$e->getMessage().'<br />';

echo ‘Source filename of exception: ‘.$e->getFile().'<br />';

echo ‘Source line of exception: ‘.$e->getLine();

exit();

}


As shown by the above hands-on example, each time the pertinent “MySQL” abstraction class throws an exception of type “MySQLException,” it will be neatly caught by the first “catch()” block and processed in a pretty trivial manner. On the other hand, all of the generic exceptions will be intercepted by the second block, in this way demonstrating how simple it is to develop a customized exception mechanism with PHP 5 by means of simple inheritance. Simple and nice, right?

Finally, I recommend that you play with all of the code samples included in this tutorial, so you can grasp more quickly how to take advantage of using exception subclasses in PHP 5-controlled applications.

Final thoughts

In this second chapter of the series, you hopefully learned how to combine a MySQL abstraction class along with a subclass derived from the built-in “Exception” parent, in order to implement a customized exception system with PHP 5. As you saw previously, this process is actually a no-brainer and can be mastered in a very short time.

You should notice, however, that all of the tasks aimed at processing MySQL result sets were handled specifically by a “Result” class. Bearing in mind this concept, in the next tutorial I’m going to teach you how to modify the signature of this particular class to provide it with the capacity for throwing data set-related exceptions.

Want to learn how this will be done? Don’t miss the next part!

[gp-comments width="770" linklove="off" ]

chat