One of the most important things in good website engineering is ensuring that when things fail, it's handled gracefully with some kind of reasonable error message returned to the user, and that the event is logged properly in the system error logs. There are basically four ways in which a WACS application is likely to fail - authentication, failure to parse the configuration files, and failure to connect to the database, and failure to find the content.
The authentication failure is pretty conclusively covered by the
core WACS check_auth
function and it's partners.
The parser is rather more tricky to cope with, and the
XML parse routines tend to just abort - it's also very all or nothing;
the file parses or it doesn't. Additionally once a configuration file is
in place, it's unlikely to become corrupted; if it's merely disappeared
the defaults will be used and the system will most likely have problems at
the next stage of connecting to the database. The third is connecting to
the database, which we'll deal with in a moment. The fourth, failure to
find content, doesn't result in completely blank screens and should get
reported to you quite quickly. Additionally there are so many places it
could be (raid parition, lvm volume, remote fileserver) that we can't
really do much in a general way.
Where we can get some traction is with decent reporting of database
connection problems, and this where the dberror
function comes into play. Previously, if we failed to connect to the
database we did the following in php:
if( DB::iserror($dbhandle)) { die("Can't connect to database\nReason:". $dbhandle->getMessage()."\n"); }
and the similar steps in perl were:
$dbhandle=DBI->connect( conf_get_attr("database","dbiconnect"), conf_get_attr("database","dbuser"), conf_get_attr("database","dbpass") ) || die("Can't connect to database\nReason given was $DBI::errstr\n");
To improve this, we're going to change this (called mysimple6 in the example code) to use the dberror function instead. This is a routine that uses named parameters, a technique we'll see a lot more of later as we use the WacsUI programming library. Basically we pass it up to five arguments or parameters, but we tell it what each one is, thus the order doesn't matter and if any of them are missing, it doesn't affect the values of the others. The dberror routine expects parameters called: header, message, error, dbuser and dbhost.
The header is to tell the routine how early
in the proceedings we are and whether we still need to start the HTML
of the web page. Setting header to y
says we do want a header added, setting it to n
says
we don't. The next one, message is the message that
the end user will see. The next three are the error message returned
by the database routines, the username it was trying to use, and the
database connect string it was trying to use. Here is the code for
doing this in PHP5:
Example 3.6. Calling dberror
for better error reporting
if( DB::iserror($dbhandle)) { $wacs->dberror( array( "header"=>"y", "message"=>"MySimple6: Can't connect to database", "error"=>$dbhandle->getMessage(), "dbuser"=>$wacs->conf_get_attr("database","dbuser"), "dbhost"=>$wacs->conf_get_attr("database","phpdbconnect") )); }
while the same basic code in perl looks a little simpler because the parameter names don't need to be packaged up into an array before they're passed:
$dbhandle=DBI->connect( conf_get_attr("database","dbiconnect"), conf_get_attr("database","dbuser"), conf_get_attr("database","dbpass") ) || dberror( header=>'n', message=>"Can't connect to database", error=>$DBI::errstr, dbuser=>conf_get_attr("database","dbuser"), dbhost=>conf_get_attr("database","dbiconnect") );
With the error reporting improved, we'll move on to other things. We'll continue to use the short form version of the error message for brevity in the later examples, but you'll know that you probably want to actually use dberror in most cases. Next up, we'll take a look at displaying set details rather than those of models....