Handling MySQL Data Set Failures in PHP 5

If you’re a PHP developer who wants to learn the basics of implementing customized exceptions in PHP 5, then look no further, because you’ve come to the right place. This is the third part of a four-part series entitled “Subclassing exceptions in PHP 5.” It teaches you how to extend the native exception mechanism bundled with PHP 5 by using inheritance, and complements the corresponding theory with copious, illustrative hands-on examples.

Having already introduced you to the main subject of this article series, it’s time to summarize the topics that were discussed in the last article, in case you haven’t read it yet. In that particular tutorial I explained how to implement a fully-functional customized exception system with PHP 5, which came in handy for handling a number of specific exceptions thrown by a basic MySQL abstraction class.

However, the most relevant part of developing such a exception handling system was the small number of steps it actually took. All I had to do was derive a basic subclass from the pertinent built-in “Exception” class, and provide it with the programming logic required to handle those MySQL-related exceptions. Period.

Of course, although PHP 5 permits us to work with exception subclasses in a relative easy way, this doesn’t mean that all of your existing or future applications must incorporate this feature. However, there’s a number of situations, particularly when working with large-scale projects, where it’s often necessary to utilize customized exceptions.

And speaking of customized exceptions, in the last article I demonstrated how to build a MySQL abstraction class that implemented these in a useful fashion, so in this third tutorial I’m going to show you how to handle all of the errors that might occur when processing MySQL data sets via a specific exception mechanism.

Are you ready to continue learning about the creation of exception subclasses with PHP 5? Let’s get going!

{mospagebreak title=Intercepting MySQL-related exceptions with PHP 5}

Before I start teaching you how to implement a custom exception system to process some errors that might arise when working with MySQL data sets, I’m going to show you the example developed in the previous tutorial of this series. In this way, it will be fresh in your mind when we start covering the new material.

In simple terms, the example in question was aimed at demonstrating how to use a MySQL abstraction class to trigger, and eventually intercept, some MySQL-related exceptions. This process required defining a couple of sample classes, called “MySQL” and “Result” respectively, in addition to deriving a subclass from the built-in “Exception” class included with PHP 5.

Below I listed the corresponding signatures for all of these classes, along with a short script that shows how to use them together. Take a look at the following code sample, please:


// 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();

}

}


// 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’);

}

}

}


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();

}


If you closely examine the above example, you’ll definitely realize how simple it is to extend the functionality of the native exceptions mechanism provided by PHP 5. As you can see, in this case the previous “MySQL” class will throw only exceptions of type “MySQLException” if an error occurs when attempting to connect to the server,  select a specified database or run queries.

Besides, it’s worth mentioning that two different “try-catch” blocks are used in this specific case. The first one will intercept only MySQL-related exceptions, while the second block will catch generic ones. Quite simple to understand, isn’t it?

Well, provided that you now understand how the previous hands-on example functions, it’s time to learn other useful things regarding the implementation of exception subclasses with PHP 5.

You previously learned how to build a MySQL abstraction class that is capable of triggering some specific exceptions. So in the following section I’m going to show you how to modify the signature of the “Result” class shown above in such a way that it will be able to throw custom exceptions only when processing MySQL result sets.

Sounds pretty interesting, right? However, to learn the full details of how this process will be performed, you’ll have to click on the link below and keep reading.

{mospagebreak title=Triggering custom exceptions when processing MySQL data sets}

As I mentioned before, my purpose here is to modify the signature of the “Result” class by providing it with the ability to throw specific exceptions when processing MySQL data sets.

Based on this idea, the pertinent “Result” class would now look as follows:


// redefine ‘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 ResultException(‘Error counting rows’);

}

return $rows;

}

// count affected rows

public function countAffectedRows(){

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

throw new ResultException(‘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 ResultException(‘Error getting ID’);

}

return $id;

}

// seek row

public function seekRow($row=0){

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

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

}

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

throw new ResultException(‘Error seeking data’);

}

}

}


That wasn’t rocket science, right? As you can see, the above “Result” class is now capable of throwing some customized exceptions of type “ResultException” each time an error occurs, either when counting and seeking rows in a result set, or when retrieving the ID of an insertion, update or deletion operation.

Of course, these same failures could have been handled through generic exceptions. In this case, however, I want to provide you with a simple example to help you learn how to create classes that trigger customized exceptions.

At this point, I’ve modified the signature of the previous “Result” class, which now will trigger a special type of exception when something goes wrong. The next step that must be taken consists of creating a subclass that handles these exceptions via a “try-catch” block.

Building such a subclass will be the last topic that I plan to discuss in this article. If you’re interested in learning how the class in question will be constructed, please click on the link below and read the next few lines.

{mospagebreak title=Handling MySQL and result set exceptions with separated try-catch blocks}

As I explained in the previous section, it’s necessary to derive a subclass from the built-in “Exception” class bundled with PHP 5 to separately handle all of the specific exceptions triggered by the “Result” class coded previously. Therefore, I’ve included the signature of this brand new exception subclass below. It is responsible only for handling some errors that might occur when processing MySQL result sets.

Here’s how this particular class looks:


// create ResultException class

class ResultException extends Exception{

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

// call parent of Exception class

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

}

public function showResultExceptionInfo(){

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

}

}


Undeniably, the definition of the above “ResultException” subclass is pretty simple. It extends the functionality of the corresponding “Exception” parent; it implements a basic method called “showResultExceptionInfo().” This method returns specific information to client code about the launched exception, including its source file, the line of code that triggered the error, and so forth. Nothing too complicated to grasp, right?

Well, now that we have derived a subclass that handles specific MySQL result set exceptions, please focus your attention on the following script. It demonstrates how to use the subclass. 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 />';

}

// throw a Result Exception

echo $result->getInsertID();

 

/* displays the following

Catching Result exceptions…

Exception message: Error getting ID

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

Source line of exception: 93

*/

}

// catch MySQL exceptions here

catch(MySQLException $e){

echo $e->showMySQLExceptionInfo();

exit();

}

// catch Result exceptions here

catch(ResultException $e){

echo $e->showResultExceptionInfo();

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 you can see from the above hands-on example, the “getInsertID()” method that belongs to the “Result” class is called deliberately. This condition immediately fires up an exception of type “ResultException,” which is finally intercepted and handled property by a specific “catch” block.

Hopefully, the previous example was useful enough to demonstrate how several types of exception can be handled within the same PHP 5 application.

Feel free to use all of the code examples developed in this tutorial to help you acquire a more solid background in working with exception subclasses within PHP 5-driven applications.

Final thoughts

In this third installment of the series, you learned how to combine three different types of exceptions in the same PHP 5 application. In this particular case, the whole process demanded that we first derive two specific subclasses from the base “Exception” class, and then include the corresponding “try-catch” blocks required to handle each kind of exception.

In the next article, I’m going to conclude this series by demonstrating how to merge the two exception subclasses that you have learned into one, which can be useful if you don’t want to clutter the source code of a web application with many “try-catch” blocks.

Now that you’ve been warned about the topics that will be discussed in the final article, you won’t want to miss it!

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

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort