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.
Related
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.
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.
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.
I have been working with Exceptions lately. I think it makes sense to log uncaught Exceptions, because it greatly helps developers to take care of possible problems in the source by simply looking at Exception log. However, when an exception is dealt with, is there a need to log it any longer? Yes, to some extent. If you have "bad" developers who write code that has bugs, then by simply catching Exceptions will make the bugs go "away". For example:
try
{
fopen('/path/to/file','w');
}
catch (Exception $e)
{
// Display an error to user
}
The above code is PHP. The point is, this kind of code, imo, should not exist. Exceptions are meant to be exceptional and occur rarely, but with this code they occur more than rarely. For instance, the developer does not check if the file exists and he does not check if he has permissions to write to it. Instead, it should be:
try
{
if (file_exists('/path/to/file') && is_writable('/path/to/file'))
fopen('/path/to/file','w');
else
// Display an error to user about file not existing or not being writable
}
catch (Exception $e)
{
// Display an error to user about an unexpected error
}
This makes pretty much sense now. The exception is thrown and caught only if it is exceptional (e.g. server crash, power outage, whatever). But what if the developer uses Exceptions for everything and the omits checks - is there a way for me to log caught exceptions?
I don't want developers to put everything in try-catch blocks to "solve" issues. I want them to explicitly check whatever they should check - and leave exceptions for exceptional situations like hardware failure, server crash, etc.
Exceptions are meant to be exceptional and occur rarely, but with this code they occur more than rarely.
I think that's a misconception. The point of exceptions is to separate the ideal flow from the error-handling flow.
You can use PHP's set_exception_handler function, this will let you supply a function that will catch all uncaught exceptions but you'll have to add manual logging for all those that are caught in your scripts.
I don't think that there's a magic method type approach if that's what you're looking for. But is it possible to wrap your entire app in a try... catch... structure? By definition, any exceptions that get to the outer-most try... catch... are uncaught... or am I missing the point ;-)
I agree with troelskn's comment that you should just embrace exceptions as a valid way to harden code.
If you still want to log the uncaught exceptions, you'd have to have all your developers pass them to a logging function (eg. log_exception($e)) or catch them all in a high-level try/catch and log them there. You could also use a tool like PHP_CodeSniffer to detect code written like your first example, but it's not a great solution. You'd need to write your own sniff to detect this case; it could look for a try block that doesn't contain any if statements.
I am switching from plain mysql in php to PDO and I have noticed that the common way to test for errors is using a try / catch combination instead of if / else combinations.
What is the advantage of that method, can I use one try / catch block instead of several nested if / else blocks to handle all errors for the different steps (connect, prepare, execute, etc.)?
I'd use the try/catch block when the normal path through the code should proceed without error unless there are truly some exceptional conditions -- like the server being down, your credentials being expired or incorrect. I wouldn't necessarily use it to handle non-exceptional errors -- say like the current user not being in the correct role. That is, when you can reasonably expect and handle an error that is not an exceptional condition, I think you should do your checks.
In the case that you've described -- setting up and performing a query, a try/catch block is an excellent way to handle it as you normally expect the query to succeed. On the other hand, you'll probably want to check that the contents of result are what you expect with control flow logic rather than just attempting to use data that may not be valid for your purpose.
One thing that you want to look out for is sloppy use of try/catch. Try/catch shouldn't be used to protect yourself from bad programming -- the "I don't know what will happen if I do this so I'm going to wrap it in a try/catch and hope for the best" kind of programming. Typically you'll want to restrict the kinds of exceptions you catch to those that are not related to the code itself (server down, bad credentials, etc.) so that you can find and fix errors that are code related (null pointers, etc.).
In general, try-catch blocks are great because they will break (move to the catch statement) whenever the exception occurs. If-else blocks rely on you predicting when the error will happen.
Edit:
Also, catch blocks won't stop your code from halting when an error is hit.
Throwing and catching an exception is an expensive operation compared with most any other primitive operation. If this is a piece of code that needs to perform well (eg, in a tight loop), you will want to look at your use case - if you expect the exceptions to be thrown relatively often, you will be better off with an if/else perforance-wise (unless the underlying code is just wrapping an exception for you, in which case there's no gain at all). If the exceptions are only thrown in rare circumstances, then you're better off with a try/catch to avoid the overhead of branching in a tight loop.
The advantage of try/catch, and exceptions in general, is more for the people developing libraries like PDO. They allow a system developer to handle undefined situations or unexpected results in a quick and easy way. Take a database connection. What should a system do if the database can't be reached. Should it halt execution? Try again? Throw a warning and continue? The system developer can't know what you'll need it to do, they they throw an exception, which you'll later catch and handle.
The advantage for you, as a consumer of the system is rather than getting some vague error code back, or a simple boolean false that it failed, you get an Exception object which will
Be named in such a way that it's more obvious what went wrong (If I remember right, PDO only has one Exception type, but other systems contain multiple exception types for different kinds of errors)
May/should contain methods and properties which can help you figure out why the exception was thrown
That's the theory anyway. There are lots of smart people who claim Exceptions are the way to go. There are also lots of smart people who think Exceptions are the devil, and a crutch for lazy system developers. There is nothing resembling consensus on this issue.
#Perchik:
My general philosophy of error handling:
You should use if / else to handle all cases you expect. You should not use try {} catch {} to handle everything (in most cases) because a useful Exception could be raised and you can learn about the presence of a bug from it. You should use try {} catch {} in situations where you suspect something can/will go wrong and you don't want it to bring down the whole system, like network timeout/file system access problems, files doesn't exist, etc.
Vexing exceptions
Try/Catch totally separates the error handling logic from the object business logic.
That’s exactly the advantage, using one try/catch instead of multiple if statements. You will also be able to catch any unanticipated errors.
Everybody else had good answers - but I figured I would throw my own in:
Try/Catch is an actual exception handling mechanism - so if you change your exceptions, it will automatically work on all try/catch statements.
Try/Catch gives the opportunity to run code even in the case of a major exception that might kill the if/else and in addition, the try statement can be rolled back (if you're savvy).
Since PDO is using objects, they are raising Exceptions if an error occur. The old mysql/mysqli were mere functions and didn't throw Exceptions they simply returned error codes. Try/catch is used when an Exception can be thrown from the code, and you catch it in the catch-clause, which is an object oriented way to handle errors. You can't catch Exceptions with if/else blocks - they share nothing with try/catch.
In php by using Try Catch with inheritence, We can throw exception from another class.
Example :- I am in the controller and validating user data by using Models.
If any error triggers, I just have to throw exception from Model methods.
The execution in try will break and catched in the Catch Block.
So There is less overhead of returning bool vales and checking that.
Apart from this Try Catch works great When using in chain ( Try - Catch inside another Try - Catch ).
This question has been asked more than a decade ago out of the wrong premise. In reality if and try are incomparable matters. Sadly, but up to this day people catastrophically confuse exceptions with try catch, thinking one is inseparable from another.
In the way it is asked, indeed it makes very little sense to change if {} to try {} in the meaning of obligatory try wrapping a single line of code to test for the error.
However the actual question is What is the advantage of using exceptions versus if {} else {}.
And it starts to make a whole world of sense immediately: exceptions allow automated error reporting, when neither try catch nor if else is ever have to be written.
An exception is essentially an automated way to write if ($result == FALSE) raise_error(); Without exceptions you are bound to test every operation's result manually. It would be just stupid to recreate the same behavior using exceptions. In most cases a thrown exception should be left alone, unless there is a certain handling scenario. In all other cases it has to bubble up elsewhere, hence no try {} catch {} has to be written.
Let's say we are writing an a/b division code and the most famous exception case has occurred i.e. 0 divide error, what do you think can be done next?
1. You can print a message and exit.
2. You can print a message and let the user re-enter the values, etc.
There are cases when different people/vendors want to handle the same exception case in different way. The catch block let them do this with ease. If you need to change the way how a certain exception case will be handled, you just need to change the catch block.
TRY/ CATCH can be used within the programming context where you have very little information about the error or you think that might can occur such as.
#include <iostream>
using namespace std;
int main (){
try{
while(true){
new int[100000];
}
}
catch(bad_alloc& e){
cout << e.what() << endl;
}
}
Although there are no semantic or compile-time errors in the program, but it's understandable that it posses a run-time error which is "bad_alloc" which appears when you try to continuously allocate the memory and your program run out of memory. This exception is defined in bad_alloc standard class which is a child-class of class "Exception", since it throws an implicit exception, throw keyword is not implied here.
You can also use try/catch to check if the file is accidentally deleted and can use if/else to check if there exists a file or not, both have their own advantages.
Try and Catch functions are useful whenever there is a communication between functions. In Try and Catch , if there exists an exception in the TRY block, the control is transferred directly to the CATCH block which would store our exception condition. This however is not possible in case of IF ELSE, where in IF condition , if there exists an exception, the control cannot go to the ELSE block howsoever in any case.
int division(int a,int b){
if(b==0)
throw 101;
return a/b;
}
int main()
{
int a=10,b=0,c;
try{
c=division(a,b);
cout<<c<<endl;
}
catch(int a){
cout<<"Division not possible by 0"<<endl;
}
}
Consider the following Code: throw and catch function is used for communication between functions division and the main function.
Note that the statement to print c is not executed when b is 0 as the control directly transfers to the catch block after the value os thrown.
This however would not have been possible , had it been IF ELSE here.