Q: What's wrong with PHP's way of handling errors & exceptions?
A: When PHP encounters an error or exception it automatically displays it on the screen in a rather nasty manner and stops the script.
Spoiler
Q: Why should I handle errors myself?
A: Handling errors will allow a programmer to determine what exactly he\she wants to do with the error message. This can be but not limited to logging it to a database, emailing the right people automatically, and redirecting a user to a specific page while letting them know the task they tried to execute was not completed. Users aren't found of seeing cryptic messages on their screen when they're just trying to view a simple web page. This will in turn deter users from using your site.
I find that the majority or newer PHP coders handle error using the die function.
$sql = "GIVE ME ALL THE TABLES"; //that should do the trick
$result = mysql_query($sql) or die("There was an error");
Remember when you did that? It may even be in that very website you're developing right now. If an error occurs die like the function name says causes the whole script to die which causes pages to be half loaded and so forth.
Q: What about the error message?
A: User's don't care about your error messages so you should keep them to yourself!!
Let's look at a more user-friendly way of handling such situations.
Setting Up Your Error Handler Function
function error_handler($errno, $error, $file, $line, $context)
{
//just so we know the error handler got the error
printf("The error handler got the error! The error says %s", $error);
return true;
}
set_error_handler('error_handler');
$sql = "GIVE ME ALL THE TABLES";
$result = mysql_query($sql);
restore_error_handler();
The above code still outputs the error message to the screen but we've seen that our error handler catches errors. Our next step is to determine what you want to do with the error.
Handling The Error Effectively
function error_handler($errno, $error, $file, $line, $context)
{
$formated_error_message = sprintf("Error caught on line #$d in script <b>%s</b><br />Cause of Error: %s", $line, $file, $error);
//let's do something useful with our error message
mail("somebody@mailhost.xxx", "Error On www.mysite.xxx", $formated_error_message, "From: error_handler@mysite.xxx\r\nX-Mailer: PHP/" . phpversion());
return true; //this notifies the script that we handled the error OK and not to call the default error handler
}
set_error_handler('error_handler');
$sql = "GIVE ME ALL THE TABLES";
$result = mysql_query($sql);
restore_error_handler();
The above snippet will attempt to email the error message to the listed recipient. You can also log your error messages to a database for an administrator or who ever else to view.
How do Create An Custom Error?
This may sound strange but there are instances where one would need to throw a particular error. For instance let's detect a mail header injection attack.
Example: Featuring trigger_error
$message = $_POST['message'];
if(preg_match("#[\n]|[\r]|[\%??]#", $message))
trigger_error("An attack has been detected");
echo "Running the rest of the script...";
If you notice the message Running the rest of the script will still appear. To prevent such we can simply use this line to trigger the error
trigger_error("An attack has been detected") and exit(); //yep it's valid PHP
Hmmm...This is still not satisfying because it ends the script execution which can lead to blank pages or half loaded pages. Let's take this next script into consideration...
set_error_handler('error_handler', E_ALL);
function redirect()
{
header("location: logger.php"); //remember not to output anything to the screen
}
$message = $_POST['message'];
if(preg_match("#[\n]|[\r]|[\%??]#", $message))
trigger_error("An attack has been detected") and redirect();
echo "Running the rest of the script...";
restore_error_handler();
That's better. If an attack has been detected then trigger_error will like the function name says trigger an error causing our error_handler to take necessary actions. After our error has been triggered our function redirect will be called. In our redirect function we can take the necessary action to handle the injection like redirecting our hacker to a script that logs their IP address etc... The possibilities are endless
My Error Handler Doesn't Capture Exceptions!
Just as there's an error handler there can be an exception handler. Exceptions are not handled by error handlers. In order to invoke your error handler when an Exception is thrown you must trigger an error manually in the catch statement. The code below demonstrates such. Notice even when we trigger the error the rest of the script is still executed.
<?php
echo "Beginning of script...<br />";
set_error_handler('error_handler', E_ALL);
function error_handler($errno, $error, $file, $line, $context)
{
echo sprintf("%d<br />%s<br />%s<br />%d<br />", $errno, $error, $file, $line);
return true;
}
try
{
throw new ErrorException("ErrorException thrown");
}
catch(ErrorException $e)
{
trigger_error($e->getMessage());
}
catch(Exception $e)
{
echo $e->getMessage();
}
restore_error_handler();
echo "End of script...";
?>
Now you've seen much better ways to handle errors other than just using die to kill the entire script. When designing for companies or clients you WILL have to handle those errors.
My Site Never Displays Errors Because I Use @
Using @ to suppress an error isn't advised. What if when someone is purchasing an item from your site and your mail function can't work because port 25 is blocked. You will never know since the error was suppressed.
Final Comments
It's better to have two ways of keeping track of errors. In the example above I only showed you 1 method which was emailing the necessary personnel. What if the mail function doesn't work. Have a second method like logging it to a database. Refrain from logging such information in TXT files. In the case of multiple users accessing a page or script containing the error there's going to be file lock issues and loss of data.
Useful Resources
Error Handling Functions
set_error_handler
set_exception_handler
restore_error_handler
restore_exception_handler
ErrorException
Exception
trigger_error
This post has been edited by codeprada: 10 May 2011 - 05:29 PM







MultiQuote







|