Building a Modular Exception Class in PHP 5 - Handling MySQL-related exceptions through one single subclass (
Page 4 of 4 )
As I anticipated in the previous section, below I developed an illustrative example to show you how the exception subclass coded previously can be utilized in conjunction with the pair of MySQL processing classes that I listed in the beginning of this tutorial.
This being said, please pay close attention to the example in question, which looks like this:
// define MySQLException subclass
class MySQLException extends Exception{
private $exceptionType;
public function __construct($message,$code=0){
// call parent of Exception class
parent::__construct($message,$code);
if($code==1){
$this->exceptionType='MySQLException';
}
elseif($code==2){
$this->exceptionType='ResultException';
}
else{
$this->exceptionType='Unknown Exception';
}
}
public function showMySQLExceptionInfo(){
return 'Catching '.$this->exceptionType.'...<br />Exception message: '.$this->getMessage().'<br />Source filename of exception: '.$this->getFile().'<br />Source line of exception: '.$this->getLine();
}
}
// define 'MySQL' class
class MySQL{
public $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',1);
}
foreach($options as $parameter=>$value){
if(!$value){
throw new MySQLException('Invalid parameter '.$parameter,1);
}
$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',1);
}
if(!mysql_select_db($this->database,$this->conId)){
throw new MySQLException('Error selecting database',1);
}
}
// run query
public function query($query){
if(!$this->result=mysql_query($query,$this->conId)){
throw new MySQLException('Error performing query '.$query,1);
}
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 MySQLException('Error counting rows',2);
}
return $rows;
}
// count affected rows
public function countAffectedRows(){
if(!$rows=mysql_affected_rows($this->mysql->conId)){
throw new MySQLException('Error counting affected rows',2);
}
return $rows;
}
// get ID of last-inserted row
public function getInsertID(){
if(!$id=mysql_insert_id($this->mysql->conId)){
throw new MySQLException('Error getting ID',2);
}
return $id;
}
// seek row
public function seekRow($row=0){
if(!is_int($row)||$row<0){
throw new MySQLException('Invalid result set offset',2);
}
if(!mysql_data_seek($this->result,$row)){
throw new MySQLException('Error seeking data',2);
}
}
}
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 and throw a MySQL exception
/* displays the following
Catching MySQLException...
Exception message: Error connecting to the server
Source filename of exception: path/to/file/exception_test.php
Source line of exception: 47
*/
// now throw a Result Exception
echo $result->getInsertID();
/* displays the following
Catching ResultException...
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 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, the previous example shows in a nutshell how to use the customized "MySQLException" subclass to handle all of the exceptions triggered by the respective "MySQL" and "Result" classes.
Speaking more specifically, I've recreated a couple of situations where the two different types of MySQL-related exceptions are intercepted by the same "catch" block and processed later by the corresponding "MySQLException" subclass. That was pretty easy to grasp, right?
And with this final hand-on example, I conclude this introduction to using exception subclasses with PHP 5. Hopefully, all of the code samples developed in the different tutorials of this series will help you learn the basic concepts of this subject with minor effort.
Final thoughts
It's hard to believe, but we've come to the end of this series. As you saw previously, creating a few exception subclasses to handle more specifically the errors that may arise during the execution of a PHP 5 application is a no-brainer process that only requires patience and practice. So, if you're armed with these two elements, success is already guaranteed!
See you in the next PHP development tutorial!