PHPWomen Site Home » Programming » Best Practices » Exceptions: errors on steroids
Exceptions: errors on steroids [message #2111] Wed, 16 July 2008 16:29 Go to next message
mvriel  is currently offline mvriel
Messages: 20
Registered: July 2008
Location: Hoorn, the Netherlands
Shiny and New
Errors are one of the most encountered things in PHP, everybody knows them and some even loathe them. Errors is that which makes PHP tell you something has gone wrong, yet to tell the user the right things is another story.

Errors generally send a message to you, the developer, about what went wrong in which line of code and usually your application dies horribly giving an ugly white screen to the end-user. You do have display_errors set to false in your production environment, right?
Sometimes you merely want to generate an error and send a response based on why the error was there to the end-user.

Example:
$res = mysql_query(‘SELECT * FRO users’) or die(‘Query failed!’);

Kids, don’t try this at home!
Why not? Well, because the statement above will send the message ‘Query failed’ to your systems error log and gives a white screen, this is bad.

What do we have to do then?
Use exceptions!
Exceptions are thrown to the calling method which in turn can catch it and do something with it. If it does not catch the exception it will drop to the next who may catch it if it wants to. When no one wants the exception a fatal error will be given and the contents of the exception passed to the errorhandler.

Why is this better?
With exceptions you can pass messages about why something went wrong to the function calling the function in which the exception was generated. To do something with the error you merely have to catch it and for example, display it in a proper way.

$res = mysql_query(‘SELECT * FRO users’);
If (!$res) {
    echo mysql_error();
}
In this example we display an error message to the user when something went wrong, we use 2 function calls to find out about something and display it to the user. Here is the same example in which we pretend that mysql_query would throw an exception (it does not in reality).
try {
    $res = mysql_query(‘SELECT * FRO users’);
} catch (Exception $e) {
    echo $e->getMessage();
}

In this case we try to catch an exception if one occurs and output its error message to the screen. In this way we don’t have to build complicated error tracking in a class and ways to output it, because the messages are part of the error.
Of course you will never display this query error message to the user (think about security) but you can probably get the idea behind what I am talking about.

How do I throw such an exception?
Just by using the throw command can you send an exception object to the calling function. Note the object part since Exceptions are Object Oriented things (another one of their advantages) and thus you will have to instantiate the object you want to throw.
throw new Exception('This is an error');

The example above throws a new exception with the message This is an error to the calling function. Easy!

Experiment with it, build your own function which throw exceptions and discover it’s potential!
Re: Exceptions: errors on even more steroids [message #2122 is a reply to message #2111 ] Mon, 21 July 2008 12:49 Go to previous messageGo to next message
dreis  is currently offline dreis
Messages: 61
Registered: October 2006
Location: The Netherlands
Junior Member

To enhance on mvriels article a bit: You can have exceptions on even more steroids:

You can create your own custom Exceptions very easily by extending the standard Exception class:

class fileException extends Exception {}

This is very handy when you want to do a bunch of stuff in one go and handle the exceptions centrally but not in exactly the same way.
(extending mvriels example):

Suppose that you want to read a value from a file just before you do the query and you've created a method to do this:

function readFile($sFileName) {
    if (!file_exists($sFileName) {
	throw new fileException('Sorry, the file could not be found.');
    } if (!is_readable($sFileName) {
	throw new fileException('Hmm, the file is not readable.');
    } 
    // read from file ...
}

Now you can:

try {
    // try to read from the file
    $value = readFile('somefile.log');

    // try to query db
    $res = mysql_query("UPDATE .... WHERE something='$value’");
} catch (fileException $e) {
    // now you can easily send a mail to the admin to tell him to create the file or similar
    echo $e->getMessage();
} catch (Exception $e) {
    // and over here you can email yourself to fix the db connection
    echo $e->getMessage();
}
// while to the user it all looks the same


This example doesn't make a whole lot of sense in the real world but I hope you get the idea.
It's very handy if you for example need to send error-messages to different people or if the flow of an application should go in different directions, depending on the exception.

Petra
Re: Exceptions: errors on steroids [message #2745 is a reply to message #2111 ] Tue, 21 July 2009 10:50 Go to previous messageGo to next message
fernando  is currently offline fernando
Messages: 1
Registered: July 2009
Shiny and New
Hi, my call that the exception does not work?

I need some extra configuration?

the method below does not enter the exception

<?php
set_error_handler(E_ALL|E_ERROR|E_WARNING|E_USER_WARNING);

try {
    $res = mysql_query('SELECT * FRO users');
} catch (Exception $e) {
    print_r($e);
}
	
?>


How i can call excepetion in this case ?
Re: Exceptions: errors on steroids [message #2747 is a reply to message #2745 ] Thu, 23 July 2009 07:27 Go to previous messageGo to next message
lorna  is currently offline lorna
Messages: 413
Registered: October 2006
Location: Leeds, UK
Feeling Comfortable

it depends whether your code can throw an exception or not - some methods will and others won't. The example you gave, mysql_query, doesn't throw an exception in the event of an error - the method will simply return false.

Since there is no exception, the catch block isn't entered. Does that make more sense?

Lorna


Lorna Mitchell (online at http://www.lornajane.net)
Re: Error handling [message #2812 is a reply to message #2111 ] Wed, 02 September 2009 16:59 Go to previous message
AlisonW  is currently offline AlisonW
Messages: 2
Registered: September 2009
Location: London
Shiny and New
the exception/throw route is great during development, but notsomuch on a live site (especially never EVER use an inline "die" on a customer-facing site!)

One way to deal with it is to handle all errors through a standardised route.

On initiating a page setup some defines for the error codes, eg
<?php
// error codes
define('ERR_USERNOTEXIST','-1');
define('ERR_INTDB','-2');
?>


then, when something causes what *you* consider to be an error, exit whereever you are and 'pop to the top', eg.
<?php
if (!$db mysql_connect(DB_SYSTEM,DB_WRITE,DB_RWP)) return ERR_INTDB// local MySQL failure
if (!$success) {mysql_close($db);return ERR_USEREXIST;};
if (!
$rslt) return ERR_EMAILSEND;
?>


then at the top level use something like
<?php
if ($rslt 0) {echo echofault($rslt, ... ); safestop(); };
?>


where that target function has something like
<?php
function echofault($faultcode, ... ) {
    global 
$svc;
    if (
$faultcode > -1) return false;
    switch (
$faultcode) {
        case 
ERR_USERNOTEXIST:
            
$rtn "That user name does not exist on ".$svc[$service]['name'].".";
            break;
        case 
ERR_INTDB:
            
$rtn =  "Internal database error.";
            break;
// etc!
        
default:
            echo 
"!!! unknown internal error, code: |$faultcode|";
            die();
        };
    return 
$rtn;
};
?>


Now, the overall script can be safely closed down (and logged!) rather than die in the middle in unknown territory.

This also has the massive advantage that all user-facing text is now in one file so i18n is far simpler and more controllable.

Previous Topic:Recursion
Next Topic:Guess the magic number: Using constants effectively in PHP
Goto Forum:
  


Current Time: Fri Jul 30 12:57:26 EDT 2010

Total time taken to generate the page: 0.01030 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.0.
Copyright ©2001-2006 FUD Forum Bulletin Board Software