Why should I use exception handling in php? - php

I've been programming PHP for a long time, but not so much PHP 5... I've known about exception handling in PHP 5 for some time, but never really looked into it. After a quick Google it seems fairly pointless to use exception handling - I can't see the advantages of using it over just using some if() {} statements, and perhaps my own error handling class or whatever.
There's got to be a bunch of good reasons for using it (I guess?!) otherwise it wouldn't have been put into the language (probably). Can anyone tell me of some good benefits it has over just using a bunch of if statements or a switch statement or something?

Exceptions allow you to distinguish between different types of errors, and is also great for routing. For example...
class Application
{
public function run()
{
try {
// Start her up!!
} catch (Exception $e) {
// If Ajax request, send back status and message
if ($this->getRequest()->isAjax()) {
return Application_Json::encode(array(
'status' => 'error',
'msg' => $e->getMessage());
}
// ...otherwise, just throw error
throw $e;
}
}
}
The thrown exception can then be handled by a custom error handler.
Since PHP is a loosely typed language, you might need to ensure that only strings are passed as arguments to a class method. For example...
class StringsOnly
{
public function onlyPassStringToThisMethod($string)
{
if (!is_string($string)) {
throw new InvalidArgumentException('$string is definitely not a string');
}
// Cool string manipulation...
return $this;
}
}
...or if you need to handle different types of exceptions in different ways.
class DifferentExceptionsForDifferentFolks
{
public function catchMeIfYouCan()
{
try {
$this->flyForFree();
} catch (CantFlyForFreeException $e) {
$this->alertAuthorities();
return 'Sorry, you can\'t fly for free dude. It just don\'t work that way!';
} catch (DbException $e) {
// Get DB debug info
$this->logDbDebugInfo();
return 'Could not access database. What did you mess up this time?';
} catch (Exception $e) {
$this->logMiscException($e);
return 'I catch all exceptions for which you did not account!';
}
}
}
If using transactions in something like Zend Framework:
class CreditCardController extends Zend_Controller_Action
{
public function buyforgirlfriendAction()
{
try {
$this->getDb()->beginTransaction();
$this->insertGift($giftName, $giftPrice, $giftWowFactor);
$this->getDb()->commit();
} catch (Exception $e) {
// Error encountered, rollback changes
$this->getDb()->rollBack();
// Re-throw exception, allow ErrorController forward
throw $e;
}
}
}

Exception handling: If condition versus Exception isn't specific to PHP, but gives a good perspective. Personally, Exception(s) & try/catch are implemented in languages to enforce good behaviour amongst developers that normally wouldn't be as attentive to error checking / handling.
If you are confident that your if/else if/else is catching all scenarios, than cool.
Here is an overview of the Advantages of Exceptions - Java -- At one point, there is a snippet of code that has many if/else statements and the following excerpt:
There's so much error detection, reporting, and returning here that the original seven lines of code are lost in the clutter. Worse yet, the logical flow of the code has also been lost, thus making it difficult to tell whether the code is doing the right thing: Is the file really being closed if the function fails to allocate enough memory? It's even more difficult to ensure that the code continues to do the right thing when you modify the method three months after writing it. Many programmers solve this problem by simply ignoring it — errors are reported when their programs crash.
So really, it comes down to personal preference in the end. If you want code that is readable and can be consumed by other people, it's generally a better approach and enforces best-behaviour

If you are following the object-oriented methodology then exceptions comes handy for the error handling. It is convenient to communicate the errors through exception across the objects.
Exceptions are really helpful if you go with layered design approach.
If you are not coding in object-oriented way, then exceptions are not required.

We use exception handling if we are not sure about the code results. We put that snippet of code in try block and catch that error in catch block. Please check this link for more information.

In general there are two good reasons to use exception handling:
You might now always know where an exception will occur - something unexpected could arise. If you use a global exception handler you can make sure that no matter what goes wrong, your program has a chance to recover. Similarly a particularly sensitive piece of code (like something that does I/O) could have all sorts of different errors that can only be detected at runtime and you want to catch any possible contingency. Some things might not occur during testing; like what if a server outside of your control fails? This may never be tested before it really happens (although good testing would include this). This is the more important reason really.
Performance. Typically exceptions are implemented so that everything is fast so long as nothing goes wrong. Exceptions are caught after they occur. This means that no 'if' statement has to be evaluated in advance if something goes wrong, and the overhead is very low in that case. If you don't use exceptions you will be forced to add a lot of 'if' statements to your code. While usually this isn't much of a problem, this can kill a performance-critical application. This is especially true because a branch mis-prediction in the CPU can cause a pipeline flush.

I that reason is that Exception is called after trigger_error(); function and you can send also some additional information to that exception = better debugging?
I'm not sure but I think that's it
example:
class db
{
function connect()
{
mysql_Connect("lolcalhost", "root", "pass:)") or trigger_error("Test");
}
}
try
{
}
catch (db

One of the primary reasons for having an exceptions framework is so that if the code ever gets to the point where it cannot proceed, it has the ability to tell the surrounding context that something has gone wrong. It means that if I have a class Foo which needs to have $fooInstance->setBarHandler($barHandler) called before $fooInstance->doFoo(); can succeed, the class can provide a message to the greater context instead of failing silently and returning FALSE. Further, it allows the context to say, "Huh. That broke. Well, I can now tell the user/logs/something else that something bad happened, and I can decide whether I need to keep on chugging."

Exceptions can provide much more data than simple -1 or false.
Exceptions can do advanced error handling. Keep in mind that try .. catch blocks can be nested and there could be more than one catch block in try .. catch block.
Exceptions force you to handle errors. When you're not using them you do something like:
function doSomething($a, $b, $c) {
...
if ($a < $b && $b > $c) {
return -1; // error
}
...
}
$d = doSomething($x, $y, $z);
if ($d === -1) {
die('Fatal error!');
}
And everything is fine as long as you remember to check whether function returned error. But what happen if you forgot to check that? It's actually a quite common problem.
Exceptions make the flow of a program much more natural.

Exceptions are hard to use in the correct context,especially in php. Personally i use exceptions when these 3 things happen:
Resource failure exception - You can throw an exception maybe when your program runs out of memory. for example in php when you run a script that exceeds 30 seconds executing. Though you can chanage that in .ini
Client code errors exceptions - For example when trying to connect to a database with the wrong credentials or unlinking a file not on server. Or when the database server is down and unresponsive, you can throw an exception.
Programmer error exception - These are errors generated due to your own coding problems.This can also be used when you are not sure of the results your code will give you. for example when dividing by 0.

Related

Handling errors in a class, what method should I use?

I have been dealing with PHP since 2000, but not very actively, and my knowledge of PHP5 is quite horrible. Recently I got my interest for webdevelopment back after a 5 year long break, and I started working on a project. I wrote a class for that project that became fairly large, but so far without any specific error handling.
The purpose of the class is to parse HTML files with a specific layout and handle its data, and it was more or less a training exercise for me to get back into the game. I started to rewrite the class now, and I decided it was time to be a little more professional about error handling than simply using die(), which I have been using a lot so far. I think we can all agree that is a terrible direction to take. I want the class to be quite project independent, so that I can distribute it to whoever wants to use it.
The HTML files I want to parse contain tables with specific bordercolors, trs with specific bgcolors, but the number of elements are dynamic. To validate that the HTML files actually have this specific pattern, I have the following sample (pseudo)code
public function Validate() {
$tables = getall('table', $this->data);
foreach ($tables as $table) {
if ($table->bordercolor != 'navy' && $table->cellspacing != 0) {
// Error
}
foreach ($tables->tr as $tr) {
if ($tr->bgcolor != '#fff') {
// Error
}
}
}
return true;
}
Where it says // Error, the HTML layout doesn't check out and my class should not attempt to parse it. Traditionally I would do this:
if ($table->bgcolor != '#fff') {
$this->error = 'Invalid HTML layout';
return false;
}
And from where I call the method I would use
if ($class->Validate() === false) {
exit_with_error($class->GetError()); // Simple return of $this->error
}
I've always thought it's a decent approach because of it's simplicity. However that's also a disadvantage as it doesn't really provide any in-depth information of the error apart from the text itself. I can't see where the error was triggered, what methods were called, etc.
Since I resumed my PHP hobby I have discovered exceptions. My problem with them is simply that I don't understand how to properly use them. And if I should use them at all. I would like my class to be portable; can I use exceptions to handle errors at all? And if yes, how can I communicate the errors (i.e. translate my traditional error handling)? Or perhaps there is an even better approach to take, which I don't know about.
Any help appreciated :)
You are certainly thinking along the right path. Typically, I like to separatte class design from error handling logic. In other words I don't want to have a bunch of $this->error = 'something' logic in the class, as why would you want to add extra code to every class to store/handle/report errors.
Now you get into exceptions vs. errors and when to use each. This is likely a subject for debate, but my personal preference has largely been to throw Exceptions in cases where you get to a point in your code that you cannot recover from or do not have the logic to handle. A great example of this, that I typically use, is throwing Exceptions right at the beginning of any class method that requires parameters of a certain sort or value. Like this example:
public method set_attribute($value) {
if (empty($value)) {
throw new Exception('You must send me something');
} else if (!is_string($value)) {
throw new Exception("You sent me something but it wasn't the string I was expecting.");
}
// method logic here
}
Here if the caller didn't give us a non-empty string, we throw an Exception, as we were not expecting this and we can't guarantee successful completion of the method without a proper value. There is not reason to continue with the method at all. We send the caller the exception with a message about the problem. Hopefully they invoked this method in a try-catch block and can gracefully handle the exception and pass it along up the call stack. If not, your code just stopped execution with fatal error from an uncaught exception (something really easy to catch in testing).
Triggering errors, I honestly use a lot less, and typically use them more for debug, warning purposes. An example of this might be a deprecated method that you still want to work, but you want to give the user an error on
public function old_method() {
trigger_error('This method had been deprecated. You should consider not using it anymore.'. E_USER_WARNING);
// method logic
}
Of course you can trigger whatever level of E_USER class warning here yourself.
Like I said, I tend to work a lot more with Exceptions, as they are also easily extensible for easy use with logging and such. I almost always would have a custom Exception class extending from PHP's base Exception class that also provides logging, etc.
The other thing to consider is global error handling and Exceptoin handling. I strongly recommend using these and having these be some of the very first lines of code in any new project. Again, it will give you much better control over how you log errors/exceptions than what you can get by default.
I don't see a problem with how you are doing it, but If you want to dive into Exceptions, learn how to use try/catch statements. Usually it would be something like this:
try {
//some code that may cause an error here
} catch (Exception e) {
//if a error is found, or an exception is thrown in the try statement, whatever here will execute
//you can get the error message by using e->getMessage()
}
you can read more about it here: http://php.net/manual/en/language.exceptions.php

Exceptions in PHP. How to use them? How to extend 'em?

Few days ago I deal with errors like this...
exit( 'Error!' );
or exit( 'Error!' );
Doh, right? =] Now I'm trying to learn Exceptions. This is how far I got...
http://pastie.org/1555970
Is that correct use of them? It would be cool that I can have more info about 'em. Like file where exception is thrown and line of that file. I know that there are build-in methods (in Exception class), but I want to somehow extend it so I don't need to write...
throw new My_Exception( '...' );
catch( My_Exception $e ) {
echo $e->my_method();
}
...but use old syntax.
throw new Exception( '...' );
catch( Exception $e ) {
echo $e->getMessage();
}
...or maybe you have any greater thought of Exceptions? How to deal with them? Help me! =]
In general you only need to echo/log exceptions, that cannot be otherwise handled. This pretty much means, that if you put your entire application within try block, there's only one place where you need to put echoing/logging logic (i.e. the catch block associated with the outermost try block).
If on the other hand the exception can be handled without stopping the application (in your example this could be providing a default numeric value, instead of incorrect value), then there's usually no need to echo/log it.
If you do want to log such exceptions (for debugging for example), then your application should contain a logging framework, so that it's enough to do in your catch blocks something like
} catch (Exception $e) {
ExceptionLogger::log($e); //static method == ugly, but it's for simplicity in this example
// do whatever needs to be done
}
log() method above would check if the logging is enabled, and if it is savenecessary data to a file.
Exceptions should be typed based upon the error that you find. The Spl Exceptions are a good start, but you really should be creating your own exceptions as well. Some common ones that I use:
FileNotFoundException extends RuntimeException <- self explanatory
HTTPException extends RuntimeException <- Used for http classes when a non-200 result is encountered
DatabaseQueryException extends LogicException <- Used for database query errors
Now, by typing them specifically, it lets you handle the errors in your code. So let's say that you want to fetch a HTTP resource. If that fails with anything but a 404, you want to try a backup URL. You could do that with:
try {
return getHttp($url1):
} catch (HttpException $e) {
if ($e->getCode() != 404) {
try {
return getHttp($url2);
} catch (HttpException $e2) {
//It's ok to ignore this, since why know it's an HTTP error and not something worse
return false;
}
} else {
return false;
}
}
As far as your example code that you posted, I would change a few things:
Change the thrown exception to InvalidArgumentException since it has more semantic meaning (I almost never throw a raw exception).
You should try to avoid catch(Exception $e) at all costs. You have no idea what exception was thrown, so how can you possibly handle it?
Only catch exceptions that you are reasonably sure you know how to handle (and outputting an error/logging is not handling, it's removing the usefulness of the exception). You should never see something like catch($e) { logerror($e); } or catch($e) { print $e->getMessage(); } since netiher is actually handling the exception.
If you don't fix or workaround the cause of the exception in your catch block, you should re-throw it. Let the code above you in the stack try to handle it. This is especially true with libraries and classes that are reused all over the place.
Now, with user interfaces, it may be acceptable to catch the exception and show the user an error message. So your example where you print the exception's message might be ok, but you'd really need to think about the use-cases of it. Are you calling it from a model or controller? If so, it may be ok display an error message. Are you calling it from a library? If so, it's probably better to let the exception bubble up.
Also, don't use a global try{} catch() {} block. Instead, install an Exception Handler to handle it for you. It's cleaner, and more semantically correct (since any try{}catch{} implies that you know how to handle the exception that you caught, whereas the exception handler is precisely meant for exceptions that weren't handled because you didn't know how to handle them.
Exceptions are for exceptional circumstances. Do not use them for all error conditions. If a user submits a password that's too short, don't throw an exception, handle that in validation. But if your hash function is expecting sha256 to be available and it isn't, that's a time for an exception. Exceptions are useful for program errors (when a condition that is unexpected happens, such as invalid input to a function), state errors (when the application enters a state that is unknown or unstable, such as if the requested view does not exist) and runtime errors (when the application encounters an error that can only be detected at runtime, such as a file-not-found error).
There is an entire page of the PHP manual devoted to extending exceptions and that page also gives you a lot of information on the methods to identify file/line number, backtrace etc. where the exception was thrown. This is the type of information that is extremely useful for debugging.

Are exceptions in php really that useful?

3 days ago I started rewriting one of my scripts in OOP using classes as a practice after reading a lot about the advantages of using OOP.
Now I'm confused weather I should use exceptions or not. They seem to make my work harder and longer.
My application check if the data was sent through an Ajax request or not then uses that info through the script.
Check this example :
/*
* The older way
*/
if($ajaxEnabled) {
$error = errorWrap('Ajax error');
} else {
$error = errorWithBackLinkWrap('NoAjax error');
}
function doSomething() {
if(empty($POST['name'])) {
die($error);
}
}
/*
* OOP way
*/
class someClass {
private $_ajaxEnabled;
public function doSomething() {
try {
if(!$this->_isDateValid()) {
if($this->$_ajaxEnabled) {
throw new ajaxException('Ajax error');
} else {
throw new noAjaxException('NOAjaxError');
}
}
} catch(ajaxException $e) {
echo $e->getErrorMessage();
} catch(noAjaxException $e) {
echo $e->getErrorMessage();
}
}
}
This code is only for demonstrating the problem, so I know there are some undefined functions in it :).
So before going oop, error handling was easier for me because I only had to echo the appropriate error.
Now using exceptions, in every function I have to check the type of connection first then write 2 catch functions for each thrown exception, which lead to a much larger code.
I'm really new to OOP in php so maybe there is a cleaner and a better way to do this, is there ?
Your question is not uncommon, whether/when to use exception is sometimes a philosophical decision and many experienced developers can't wrap their heads around it.
That being said, I've found that listing out the distinct properties of each way of handling error makes it easy to choose your preferred way:
Return code
The caller can ignore it or forget to check it
The caller usually needs more documentation reading before he can use it (does 0 mean success or failure?)
Object destruction is not guaranteed -- it all depends on the caller to clean up properly
When to use: It's pretty obvious. Use return codes when you trust the caller (internal code or trivial errors which can be safely ignored).
Exceptions
The caller cannot ignore it
The caller can still suppress it if he wants (with an empty try/catch)
Object destruction takes places properly -- most of the time
When to use: When you don't trust your caller as much (third party) or you really need to make sure your error code doesn't go ignored.
Die
Cannot be ignored and cannot be suppressed
When to use: It's usually obvious enough. You need everything to stop immediately.
(In a PHP context, I don't think it makes much difference. The above suggestions should still apply.)
(Aside)
Usually it's tempting to just write out an error message when something bad happens (especially when the first programming language you learned is PHP :P). But if you really want to grok OOP, it's not a proper way to handle errors.
Every object or every function should ideally only perform one function. If one function writes error to the screen and does its own thing, it's difficult to later switch to a DatabaseErrorLogger or TextFileErrorLogger or etc. One approach would be to supply a logger to use (this is called Dependency Injection). Another way to do it is to use exception -- this way, the caller gets to choose which ErrorLogger to use.
Exceptions as an error handling mechanism are VERY different in concept and implementation than function return codes. You cannot/should not simply map one to the other. You should read and digest this article (and then a few more including this one*) before proceeding further.
If you're going to favor exceptions instead of return codes for error reporting/handling then the structure of your code should change significantly.
(*The CodeProject link is .NET-specific but there's little code ti digest. It's mostly a best-practices article easily applicable to any language.)
You shouldn't use exceptions when your code can handle the error gracefully using an if statement (like you did there on your example).
Exceptions are for situation that are well, exceptional. Unfortunately this is not very straightforward, so it's up to you, the programmer, to decide what is exceptional or not. I think a good rule of thumb is:
Avoid using exceptions to indicate
conditions that can reasonably be
expected as part of the typical
functioning of the method.
From: http://www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx
Exceptions' usefullness is not in printing error codes. It's in catching error so you can try to solve them instead of crashing with fireworks.
If I understand how you're doing it, I think you're doing it wrong. Exceptions for not for errors. They are for exceptional circumstances. Errors can mean any number of things (for example, a user didn't enter a long enough user name on a registration form). That itself shouldn't be an exception. You could however use an exception to show that registration itself failed (Depending on the situation)...
And you don't need to have a try/catch block at every level. In fact, that's bad practice. Only catch exceptions if you either can handle the exception, or need to do something else before letting the exception continue. So, for example: If you are connecting to a remote set of websites, and the first one fails. You can catch the exception for that one, and retry with a second website. And keep going until you have no more left (at which point you'd throw another exception to indicate that no websites could be fetched). Another example would be if you're generating images. You have a method that does some computation while generating the image that throws an exception. You'll want to catch that exception so that you can "clean up" from the image process (to save memory, etc) and then re-throw it once you're done: catch (ImageSomethingException $e) { /* Clean up here */ throw $e; }...
The true power of exceptions is that it lets you handle the situations however you want (since the exception can just bubble up to the top of the program). But only catch exceptions where you know you can deal with them (or at least need to clean up). You should almost never do print $e->getMessage() inside of production code.
Personally, I have a default exception handler that I always install. Basically, if an exception is not caught, it will log that exception and then generate a 500 error page. That lets me focus on what exceptions I can deal with in code instead of trying to catch everything (which isn't usually a great idea)...
Good luck...
I personally hate exceptions. I don't work with them in my applications. I prefer functions returning (and expecting) defined status codes, and dealing with recoverable errors on that level.
In truly exceptional situations (like an unreachable database server, a file I/O error etc.) that are an immediate emergency, I tend to trigger and handle a fatal error. (Object shutdown will still take place, so any connections that need closing etc. will still be handled as long as they are placed in destructor functions.)
Third party libraries' exceptions I strive to catch as quickly as possible, and deal with them in my own way.
Joel Spolsky puts the reasons much better than I could in his notorious Exceptions essay.
Note that this is one view and one school of thought. There is a lot of brilliant software whose error handling is based entirely on exceptions, and that is perfectly fine. The key is consistence - either you make the design decision to use them, or you don't.
There is a finite capacity to most development processes - i.e. even where its possible to predict all possible circumstances that the code might run in (i.e. all possible combinations of inputs, all possible states for supporting systems like database, DNS, existing data etc) then its just not practical to deal with every scenario. Using exceptions allows you:
to bundle a series of operations into one entity for the purposes of determining success/ failure as a whole
handle multiple different modes of failures with a single bit of code
So yes - I'd say that exception handling is a useful practice - but not a substitute for handling the common failure modes specifically, intelligently and informatively (and typed exceptions are IMHO a complete oxymoron).
If all you need is to display error message, why don't you use
catch (Exception $e)
{ print ($e->getMessage()); }
Its a developers call.. not mandatory as kizzx2 told.
But if you are writing up some util or library kind of class its always good to throw exception as this lib or util may be used by others in future.

Is it best practice to try - catch my entire PHP code, or be as specific as possible?

I do not have many kinds of Exceptions in my project.
Right now,(we use MVC) I have the try catch encompassing my entire code:
try{
fronController::dispatch($somthing...);
}catch(Exception $E){
//handle errors
}
I wonder if there is a good reason to use the try-catch block in as specific as possible way as I can or just keep it general as it is now?
The idea of an exception is so that a function can report failure without having to return special values. In ye old PHP, the only way a function could say it had a problem was by returning some special value like false or -1. This is not pleasant. For example, suppose I am writing a variant of file_get_contents().
The typical return value is a handle - represented by a positive integer. However, there are two basic problems I can encounter: the file you specified was not found, or the file you specified was not readable. To indicate an error I might return a negative number - because handles are positive - that associates to the particular cause of error. Let's say that -1 means the file wasn't there and -2 means the file wasn't readable.
Now we have a problem that -1 and -2 do not inherently mean anything to someone reading the code. To rectify this we introduce the global constants FILE_NOT_FOUND and FILE_NOT_READABLE. Let's see some resultant code.
<?php
define('FILE_NOT_FOUND', -1);
define('FILE_NOT_READABLE', -2);
function my_file_get_contents($file) {
// blah blah blah
}
$friendListFile = getDefaultFriendListFile();
$result = my_file_get_contents($friendListFile);
if ($result == FILE_NOT_FOUND) {
deleteFriendListFromMenu();
} elseif ($result == FILE_NOT_READABLE) {
alertUserAboutPermissionProblem();
} else {
useFriendList($result);
}
By having different error codes we can act accordingly to what the problem really is. That functionality is well and fine. The issue is purely in how the code reads.
$result is a horrible variable name. Variable names should be descriptive and obvious, like $friendListFile. The real name for $result is $fileContentsOrErrorCode which is not only too long, it examplifies how we are overloading a single variable with two meanings. You never, ever, want to have the same data mean two things. We want a separate $errorCode and $fileContents!
So how do we get around this problem? One not-really-a-solution some PHP libraries have used is to have their my_file_get_contents()-like functions return false if they encounter a problem. To disambiguate what the problem actually was we instead call my_file_get_contents_getError(). This almost works.
define('FILE_OKAY', 0);
define('FILE_NOT_FOUND', -1);
define('FILE_NOT_READABLE', -2);
$my_file_get_contents_error = FILE_OKAY;
function my_file_get_contents_getError() {
// blah blah blah
}
function my_file_get_contents($file) {
global $my_file_get_contents_error;
// blah blah blah
// whoa, an error? return false and store the error code in
// $my_file_get_contents_error
// no error? set $my_file_get_contents_error to FILE_OKAY
}
$friendListFile = getDefaultFriendListFile();
$result = my_file_get_contents($friendListFile);
if (my_file_get_contents_getError() == FILE_NOT_FOUND) {
deleteFriendListFromMenu();
} elseif (my_file_get_contents_getError() == FILE_NOT_READABLE) {
alertUserAboutPermissionProblem();
} elseif (my_file_get_contents_getError() == FILE_OKAY) {
useFriendList($result);
} else {
die('I have no idea what happened. my_file_get_contents_getError() returns '
. my_file_get_contents_getError()
);
}
As a note, yes, we can do a much better job by avoiding a global variable and other such little bits. Consider this the nuts-and-bolts demonstration.
We still cannot call $result anything better than $fileContentsOrFalseIfError. That problem has not been fixed.
I have now rectified one problem that you may have noticed in the earlier example. What if we do not cover all of the error codes? If a programmer decides that there needs to be a -3 code we weren't originally detecting it! We could have checked if $result was a string to make sure it wasn't an error code, but we aren't supposed to really care about types in PHP, right? Now that we can utilize a second return value from my_file_get_contents_getError() it is no problem to include a success code.
There is now a brand new problem that has emerged. Fix one and find three more eh? The new problem is that only the most-recent error code can be kept. This is terribly fragile! If anything else calls my_file_get_contents() before you deal with your error code, their code will overwrite yours!
Gah, now we need to keep a list of functions that are unsafe to call before you deal with the return value from my_file_get_contents_getError(). If you don't do that, you have to keep as an ad-hoc coding convention that you always call my_file_get_contents_getError() immediately after my_file_get_contents() in order to save the error code that belongs to you before it is mysteriously overwritten.
Wait! Why don't we just hand out identifiers to our callers? In order to use my_file_get_contents() you now have to ask create_my_file_get_contents_handle() for some number that will disambiguate you with all other callers. Now you can call my_file_get_contents($myHandle, $myFile) and the error code can be stored in a special location just for you. Now when you call my_file_get_contents_getError($myHandle) you can access that special place, get your error code, and no one has stepped on your toes.
Er, but if there are many callers we don't want to have zillions of useless error codes laying around. We had better ask users to call destroy_my_file_get_contents_handle($myHandle) when they are done so we can free some memory.
I hope this is all feeling very familiar to ye old PHP mantras.
This is all so crazy, just make it simple, please!
What would it mean if the language supported a better mechanism to react to errors? Clearly, trying to create some solution with the existing tools is confusing, obnoxious, and error-prone.
Enter exceptions!
<?php
class FileNotFoundException extends Exception {}
class FileNotReadableException extends Exception {}
function my_file_get_contents($file) {
if (!is_file($file)) {
throw new FileNotFoundException($file);
} elseif (!is_readable($file)) {
throw new FileNotReadableException($file);
} else {
// blah blah blah
}
}
$friendListFile = getDefaultFriendListFile();
try {
$fileContents = my_file_get_contents($friendListFile);
useFriendList($fileContents);
} catch (FileNotFoundException $e) {
deleteFriendListFromMenu();
} catch (FileNotReadableException $e) {
alertUserAboutPermissionProblem();
}
All of a sudden our old headaches of special return values and handles and coding conventions have been cured!
We can now truly rename $result to $fileContents. If my_file_get_contents() has a problem, the assignment is aborted altogether and we jump right down to the appropriate catch block. Only if there is no error do we even think about giving $fileContents a value or calling useFriendList().
No longer are we plagued by multiple callers stepping on each other's error codes! Every call to my_file_get_contents() will instantiate its own exceptions, if the error arises.
No memory problems! The garbage collector will happily clean up no-longer-used exception objects without you thinking about it. Using ye old handle system we had to remember to manually destroy the handle, lest have it lurk around forever in memory.
There are many other benefits and traits to exceptions. I strongly recommend looking to other sources to learn about these. Particularly interesting are how they bubble up the execution stack until some caller can catch them. Also interesting is how you can catch an exception, try to fix the problem, and then rethrow the exception if you can not. Do not forget that exceptions are objects! There is loads of flexibility to be gained by that. For exceptions that no one can catch, look into the exception handler.
My intent to answer the question was to demonstrate why we need exceptions. By doing this, I hope it is easy to infer what problems we can solve with them.
generally throw locally, catch globally unless an exception handler is specific to a function in which case handle locally.
class fooException extends Exception{}
// DB CLASS
public function Open(){
// open DB connection
...
if ($this->Conn->connect_errno)
throw new fooException("Could not connect: " . $this->Conn->connect_error);
}
// MAIN CLASS
public final function Main(){
try{
// do stuff
}
catch(fooException $ex){
//handle fooExceptions
}
}
Remember that exceptions are for exceptional cases. As I understand that, that happens when the error is out of your control. For example, invalid parameters are passed to a public API function, division by zero, situations like 'network connection lost', 'file not found'... this kind of things.
As a general rule, you should catch the exceptions that you know how to handle, like recovering from the error, log the error and propagate it, etc. If you don't know how to handle it, it's better to let it fail. Otherwise your application could be in an error state that you may not want.
So answering your question, it's better to be as specific as possible since every exception should be handled only if you know what to do with it (silently swallowing is a bad idea). If not just let the exception notify the user that something went wrong. Or if you want to, catch the exception to log the error and rethrow it.
There's good discussion here for C++, but the general concepts apply. I found the java tutorials on exceptions also very good.
You should be as specific as possible with catching errors in your code. Catching specific errors appropriately increases code maintainability, makes your code structured and organized.
It is also good practice as a convention, especially if you later work on team-based projects and you're not the only one looking at the code.
Personally throwing everything into one try catch block seems to be a code smell.
If you are using a try block for all your code, you might as well define a default exception handler (see the docs).
Other than that, the size of the try block is up to you, it depends on how fine you want your error handling to be. If you can't recover from any of the exceptions, there's really no reason to be specific, unless you want to log error messages that are specific (but the message of the exception and the stack trace will probably be enough).
If your handling all of your errors with one general catch you will get minimal feedback and options when an error does occour, it may be fine during development but when its on the front line it could cause you no end of problems.
Be specific and cover all of your bases where feedback is needed and recoverablity is possible.
Different errors may require different responses.
You wouldn't jump out of an airplane in response to every possible problem that could arise. Would you?
Well, that's what your app is doing.
There are situations where an exception can be caught and the application could continue to run. More likely, the app may need to respond to the same class of exception differently in different situations. Perhaps in one function an I/O exception isn't detrimental but in another it is.

Exceptions: Is this a good practice?

This is written in PHP, but it's really language agnostic.
try
{
try
{
$issue = new DM_Issue($core->db->escape_string($_GET['issue']));
}
catch(DM_Exception $e)
{
throw new Error_Page($tpl, ERR_NOT_FOUND, $e->getMessage());
}
}
catch(Error_Page $e)
{
die($e);
}
Is nested try, catch blocks a good practice to follow? It seems a little bulky just for an error page - however my Issue Datamanager throws an Exception if an error occurs and I consider that to be a good way of error detecting.
The Error_Page exception is simply an error page compiler.
I might just be pedantic, but do you think this is a good way to report errors and if so can you suggest a better way to write this?
Thanks
You're using Exceptions for page logic, and I personally think that's not a good thing. Exceptions should be used to signal when bad or unexpected things happen, not to control the output of an error page. If you want to generate an error page based on Exceptions, consider using set_exception_handler. Any uncaught exceptions are run through whatever callback method you specify. Keep in mind that this doesn't stop the "fatalness" of an Exception. After an exception is passed through your callback, execution will stop like normal after any uncaught exception.
I think you'd be better off not nesting. If you expect multiple exception types, have multiple catches.
try{
Something();
}
catch( SpecificException se )
{blah();}
catch( AnotherException ae )
{blah();}
The ideal is for exceptions to be caught at the level which can handle them. Not before (waste of time), and not after (you lose context).
So, if $tpl and ERR_NOT_FOUND are information which is only "known" close to the new DM_Issue call, for example because there are other places where you create a DM_Issue and would want ERR_SOMETHING_ELSE, or because the value of $tpl varies, then you're catching the first exception at the right place.
How to get from that place to dying is another question. An alternative would be to die right there. But if you do that then there's no opportunity for intervening code to do anything (such as clearing something up in some way or modifying the error page) after the error but before exit. It's also good to have explicit control flow. So I think you're good.
I'm assuming that your example isn't a complete application - if it is then it's probably needlessly verbose, and you could just die in the DM_Exception catch clause. But for a real app I approve of the principle of not just dying in the middle of nowhere.
Depending on your needs this could be fine, but I am generally pretty hesitant to catch an exception, wrap the message in a new exception, and rethrow it because you loose the stack trace (and potentially other) information from the original exception in the wrapping exception. If you're sure that you don't need that information when examining the wrapping exception then it's probably alright.
I'm not sure about PHP but in e.g. C# you can have more then one catch-Block so there is no need for nested try/catch-combinations.
Generally I believe that errorhandling with try/catch/finally is always common-sense, also for showing "only" a error-page. It's a clean way to handle errors and avoid strange behavior on crashing.
I wouldn't throw an exception on issue not found - it's a valid state of an application, and you don't need a stack trace just to display a 404.
What you need to catch is unexpected failures, like sql errors - that's when exception handling comes in handy. I would change your code to look more like this:
try {
$issue = DM_Issue::fetch($core->db->escape_string($_GET['issue']));
}
catch (SQLException $e) {
log_error('SQL Error: DM_Issue::fetch()', $e->get_message());
}
catch (Exception $e) {
log_error('Exception: DM_Issue::fetch()', $e->get_message());
}
if(!$issue) {
display_error_page($tpl, ERR_NOT_FOUND);
}
else
{
// ... do stuff with $issue object.
}
Exceptions should be used only if there is a potentially site-breaking event - such as a database query not executing properly or something is misconfigured. A good example is that a cache or log directory is not writable by the Apache process.
The idea here is that exceptions are for you, the developer, to halt code that can break the entire site so you can fix them before deployment. They are also sanity checks to make sure that if the environment changes (i.e. somebody alters the permissions of the cache folder or change the database scheme) the site is halted before it can damage anything.
So, no; nested catch handlers are not a good idea. In my pages, my index.php file wraps its code in a try...cache block - and if something bad happens it checks to see if its in production or not; and either emails me and display a generic error page, or shows the error right on the screen.
Remember: PHP is not C#. C# is (with the exception (hehe, no pun intended :p) of ASP.net) for applications that contain state - whereas PHP is a stateless scripting language.

Categories