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:
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:
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.