Database Abstraction With PHP - Catch Me If You Can (
Page 10 of 11 )
Now, while the
error-handling technique described on the previous page works great so long as
you only have a couple of queries running in each script, it can get tedious if
you need to execute eight, ten or a hundred queries within a script. Which is
why the abstraction layer also provides a generic way to trap and resolve
errors, via a default error handler.
This default error handling
mechanism can be defined through the setErrorHandling() method, and it accepts
any one of the following five parameters:
PEAR_ERROR_RETURN - do nothing
PEAR_ERROR_PRINT - print the error message but continue executing the script
PEAR_ERROR_TRIGGER - trigger a PHP error PEAR_ERROR_DIE - terminate script
execution PEAR_ERROR_CALLBACK - call another function to handle the
error
Let's see this in action:
<?php
// uncomment this to see plaintext output in your browser
// header("Content-Type: text/plain");
// include the DB abstraction layer
include("DB.php");
// connect to the database
$dbh = DB::connect("mysql://john:doe@localhost/db287");
// set an error handler
$dbh->setErrorHandling(PEAR_ERROR_PRINT, "The database said: %s");
// run a sequence of queries
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title A', 'Artist
A')");
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title B', 'Artist
B')");
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title C', Artist
C')");
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title D', 'Artist
D')");
// close database connection
$dbh->disconnect();
?>
In this case, the third query contains a syntax error (a
missing quote). When this error is encountered, an exception is raised and the
error handler is invoked to handle the error. Since I've specified
<?
// set an error handler
$dbh->setErrorHandling(PEAR_ERROR_PRINT, "The database said: %s");
?>
an error message will appear, but the script will move on to
execute the fourth query.
Here's the output:
The database said: DB Error: syntax error
In case you're wondering, the second argument to the
setErrorHandling() method above is an optional string that can be used to apply
basic formatting to the error message. You can omit it if you like - the output
will look just as pretty without it.
You can also specify a callback
function of your own to handle the error, in case you want to do something
complicated with it - for example, insert it into a table, or log it to a file.
In such a situation, the setErrorHandling() function must be passed two
arguments: the constant PEAR_ERROR_CALLBACK, and the name of your user-defined
error handler. If an error occurs, this error handler is invoked with an object
as argument; this object represents the error, and its properties hold detailed
information on what went wrong.
If all this sounds a little complicated,
the next example might make it easier to understand:
<?php
// uncomment this to see plaintext output in your browser
// header("Content-Type: text/plain");
// include the DB abstraction layer
include("DB.php");
// connect to the database
$dbh = DB::connect("mysql://john:doe@localhost/db287");
// set an error handler
$dbh->setErrorHandling(PEAR_ERROR_CALLBACK, "catchMe");
// run a sequence of queries
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title A', 'Artist
A')");
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title B', 'Artist
B')");
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title C', Artist
C')");
$dbh->query("INSERT INTO cds (title, artist) VALUES ('Title D', 'Artist
D')");
// close database connection
$dbh->disconnect();
// user-defined error handler
// logs errors to a file
function catchMe(&$obj)
{
// uncomment next line to see object properties
// print_r($obj);
// create a string to hold the error
// access object properties to get different bits of information about the
error
$str = "Timestamp: " . date("d-M-Y h:m", mktime()) . "\n";
$str .= "Error code: " . $obj->code . "\n";
$str .= "Error message: " . $obj->message . "\n";
$str .= "Debug string: " . $obj->userinfo . "\n\n";
// append error string to a log file
$fp = fopen("error.log", "a+") or die("Could not open log file");
fwrite($fp, $str);
fclose($fp);
}
?>
In this case, I'm logging every error that occurs to a log
file using my own little catchMe() function. This function receives an object
when an error occurs; this object can be manipulated to expose detailed
information about the error (including the raw error message returned by the
server), and this information can then be written to a file.