TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Advertisement
Using Exceptions to Provide Better Feedback
   Within this article, we'll be taking a closer inspection of exceptions, as requested by the lovely Haris. This will be a basic exceptions article and so I won't be going over how to extend onto the exceptions class to model your own - otherwise we'll get too far ahead of ourselves. Exceptions tend to be used where we have no jurisdiction over the source, and when we wish to return a more informative message to the front-end.

So let's stick our hands in the sand and start playing! Consider the following simple, pseudo-like function:

php Code:
if(/* File doesn't exist */)
{
    return false;
}

if(/* File is empty */)
{
    return false;
}

If our script returned false, how on earth would we know if the file is empty or if it simply does not exist? The truth is we don't because of the ambiguity of false. Instead what we could do is throw an exception and then catch it on the front-end and thus giving us a more informative error - accompanied with an option error code, too. That is the power of exceptions!

Let's build a simple function to follow-through in this article. I'll be using this function:

php Code:
function getFileStatus($szFilename)
{
    if(!file_exists($szFilename))
    {
        return false;
    }
   
    if(filesize($szFilename) == 0)
    {
        return false;
    }
   
    return true;
}

The function is rather simple, it first checks to see if it exists, and then checks to see if its file size is zero. Whereas if it exists and has a file size greater than 0, it returns true. As there is only 1 instance of the true boolean, we know that if we do not have a false then we're good to go, but what if we wanted to perform further actions to perhaps create the file if it doesn't exist? But perform another action to populate it if it is empty? We'll have to start throwing some exceptions!

php Code:
if(!file_exists($szFilename))
{
    throw new Exception('File does not exist');
}

if(filesize($szFilename) == 0)
{
    throw new Exception('File is empty');
}

We're effectively saying now if one of our if statements fail, then throw a new exception to the front-end for it to catch. Therefore when we call our function we first try it, and then catch any errors. That's all there really is to exceptions on this primitive level:

Try a block of code -> Throw any exceptions -> Catch any errors


The following code is our call to our function encapsulated by a try block and then immediately following it, a catch block to catch any errors that our function may have thrown, of which it has the distinct possibility of throwing either of the 2 we've defined.

php Code:
try
{
    getFileStatus('1.txt');
}
catch(Exception $pEx)
{
    echo $pEx->getMessage();
}

If there are no exceptions in our function then our code will merrily skip the catch block and continue on with the code below. Whereas in our function, if the code reaches a throw new statement then it will not continue on executing that particular function - it will essentially ask the code inside the catch block what to do next. For if the catch statement were to now shrug its shoulders, our exceptions would be pretty pointless and so we echo out the error:

php Code:
echo $pEx->getMessage();

The actual catch block may seem rather perplexing on first glance, but allow me to explain. The line that you may be unfamiliar with is the following:

php Code:
catch(Exception $pEx)

Though all that line says catch any errors. We're using a type hint called Exception which means that the object pointer, $pEx must be an instance of the exception class, and not an object of any other class, such as DateTime or DateTimeZone classes.

Once we have caught the exception we are able to access its methods. The methods are listed below which you are able to access via $pEx (ignoring any magic methods of which there are __construct, __clone and __toString):
  • getCode(): This allows us to get the code we set on the exception, in our case we haven't set one.
  • getFile(): The file in which the exception was thrown.
  • getLine(): The line in which the exception was thrown.
  • getMessage(): The one we're using above, returns the message that er have set for our exception.
  • getTrace(): Returns a lot of information regarding the error as an array. Including, but not limited to, the file, line, function and the function's arguments.
  • getTraceAsString(): Same as above but returns it all as a string.

If we wanted to set an error code for our exceptions then we can use the second argument in the throw new Exception line, like so:

php Code:
if(!file_exists($szFilename))
{
    throw new Exception('File does not exist.', 1);
}

if(filesize($szFilename) == 0)
{
    throw new Exception('File is empty.', 2);
}

Our 2 exceptions now have error codes associated with them. This allows us to reference them by their error code if you wanted to add a little ambiguity to your errors - albeit you could also use the error codes to act upon like so:

php Code:
if($pEx->getCode() == 1)
{
    /* Do something to remedy the problem. */
}

If you were to omit the catch block then PHP would throw you back a fairly nasty code. One I'm sure you've seen on websites that use Javascript many a times - I know I have. If you wish to witness some first hand then there's a vast amount on Squidoo - And yes, you're spot on, I really do despise that site for its atrocious coding.

This is what an uncaught exception looks like, and because of what it looks like, you'd be well advised to catch your exceptions at any cost!

Quote:
Fatal error: Uncaught exception 'Exception' with message 'File does not exist.' in C:\wamp\www\file.php:7 Stack trace: #0 C:\wamp\www\file.php(18): getFileStatus('1.txt') #1 {main} thrown in C:\wamp\www\file.php on line 7
Luckily, there is a more friendly approach to dealing with uncaught exceptions. PHP provides us with the function set_exception_handler which gives us a last-ditch attempt at dying gracefully:

php Code:
set_exception_handler('getUncaughtEx');

For then we would create our getUncaughtEx function like so:

php Code:
function getUncaughtEx()
{
    die('Psssh! Some fish brain forgot to catch an exception.');
}

And thus instead of both confusing and boring your users with the unattractive uncaught exception error, you give them the opportunity to have a giggle at your expense. All flock, all flock!

Exceptions do of course become rather more complicated when you begin extending onto the exception class itself. This allows you to do pretty much anything you can imagine with exceptions. An exception can even be thrown and then passed through a series of catch statements - but as mentioned towards the beginning of this article, way out of the scope of this article. Hold on for the next instalment! However, the next time you find yourself dealing with outside sources or returning false too many times in a single function - consider introducing the unsurpassed power of exceptions into your code.
Report this Article
Last 5 Article Reviews Read All Reviews
   Overhead with exceptions
Review added by Dog Cow on 02-03-2009
Keep in mind that each Exception thrown adds some server overhead just like instantiating any other object. That should definitely be something to keep in mind when deciding to use exceptions for everything.

See this URL for some more details: http://jmz.iki.fi/blog/programming/php5_exception_overhead
   Fantastic!
Review added by joeaston on 03-23-2008
Great article.

Very well written and very helpful for someone like me who has very little understanding of the new OOP features in PHP5.

I'm looking forward to the next installment!

All times are GMT. The time now is 09:28 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design