If you haven't done so during your OO programming, i would recommend using a custom Exception class.
For the main reason, you can customise the __toString() so that you can output your own custom Exception text.
Now the __toString() is good for beginners to learn how to extend, but i discovered that there was not an easy way (at first glance) to handle debugging in some situations.
Say you have a database class which you include into many of your php class files so that you can access everything easily.
Now that is all well and good, but have you ever tried to add Exception's into that by doing something similar to the following?
Code: Select all
class dbConnector{
public function query($query, $_return = false){
try{
if($_return){
return mysql_query($query, $this->link);
}
$this->result = mysql_query($query, $this->link);
if(!$this->result){
throw new Exception ( sprintf("MySQL.Error: %s", mysql_error()));
}
return true;
}catch (Exception $e){
die( $e );
}
}
}If you have ever tried to debug a class which extends (in this case) dbConnector and you get and error in your query such as "MySQL.Error: Table 'mydatabase.mytable' doesn't exist"
And then thought to yourself, "Geez, where was that query that caused that error"
You may or may not have thought to try and use __CLASS__, __FILE__ with __LINE__ to try and find the place where the problem occurred.
Well this is all well and good although do you really want to worry about writing any of those magic constants every time you have an error just to make sure you know where the problem lies?
Well Exceptions have a nifty function called getTrace() which returns an array of debug trace results which happens to include the class names and line numbers for each function call it passes through.
Extending Exceptions
Code: Select all
final public function getMessage(); // message of exception
final public function getCode(); // code of exception
final public function getFile(); // source filename
final public function getLine(); // source line
final public function getTrace(); // an array of the backtrace()
final public function getPrevious(); // previous exception
final public function getTraceAsString(); // formatted string of traceSo what we can do when we create out own extended Exception class (MYException), is make use of this stack trace feature to resolve the true location of the error.
Code: Select all
<?php
class MYException extends Exception{
private $debug;
public function __Construct($message, $code = 0, $debug = false) {
// construct the parent Exception class
$this->debug = $debug;
parent::__Construct($message, $code);
}
// custom string representation of object
public function __toString() {
if(!$this->debug){
return "\r\n<strong id='error'>[{$this->code}]: {$this->message}</strong><br/>\n";
}
$_debug = $this->getTrace();
$_str = $_debug[1]['class'].":".$_debug[1]['line'];
return "\r\n<strong id='error'>{$_str} [{$this->code}]: {$this->message}</strong><br/>\n";
}
public function customFunction() {
print "A custom function for this type of exception\n";
}
}
?>Because getTrace() will always return entry [0] as the current class, we can specify the position [1] instead which gets us the class immediately next in line for the stack trace.
Note: This will ONLY resolve the next class in the chain where it is being called from. In most cases this would be true, but remember this is NOT a full stack trace, we just dont want to report the dbConnector class as the problem.
So now to use this trace, we can modify our query function to look like this instead.
Code: Select all
public function query($query, $_return = false){
try{
if($_return){
return mysql_query($query, $this->link);
}
$this->result = mysql_query($query, $this->link);
if(!$this->result){
throw new MYException( sprintf("MySQL.Error: %s", mysql_error()), mysql_errno(), true); //notice the true here to enable the debugging?
}
return true;
}catch (MYException $e){
/*
* We don't want to handle the error here, hand it back
* to the class calling the query.
*/
throw $e;
}
}And now, nothing changes in our original function (except that we should be using a try{}catch{} statement
Code: Select all
public function my_function(){
try{
$q = $this->query("select * from mytable where id = '1'");
while($r = $this->fetch("assoc")){
$row[] = $r;
}
return $row;
}catch( MYException $e ){
die($e);
}