Exception catching: when not to catch them? - php

I had been writing number of small libraries (bunch of classes) for my application inside PHP's Zend Framework. I had also been catching these exceptions inside the library's methods itself and logging them to a file.
Then suddenly I ran to an issue that my main application that was using these libraries would not quit due to errors even in situations I expected them to quit due to a fatal error. The problem with this was the code below kept executing till the end - which it should not have.
It seems like its not a good practice to catch and perhaps log majority (except in special cases) of the errors inside the library classes. They should always throw the error as it is? Would that be a correct assumption?
I'd appreciate if anyone could answer this for me.

The general philosophy of exceptions, in any language, is that they communicate exceptional circumstances. You should use them accordingly.
If you end up surrounding every function call with a try block, something is wrong. Exceptions are precisely designed to make error handling logical and not require the programmer to track all possible error paths. Therefore, you should catch exceptions precisely at those points where you can respond meaningfully to them.
If you cannot think of anything better to do than to abort and propagate the error, then there's no point catching an exception. On the other hand, if there are some errors to which you can react sensibly, catch those, and rethrow anything else.
A typical example is if you're processing lots of files. If there's an error anywhere inside the parsing logic, there's nothing you can do, even though parsing may go down many function calls. However, at the main loop you can try parsing each file, and if there's an exception, you catch that, skip the file and continue with the next one.
If you're writing a library function, you might want to have one final try block surrounding your entire function; that's somewhat up to you, though. Just document cleanly which exceptions the user has to expect from your library.

Catching and handling all exceptions is a good idea. If you don't know for sure the exception is safe to ignore (e.g. one thrown by your own code), display an error page. Do not simply re-throw it since there's nothing worse than presenting a blank page or the default error page of the webserver - or even a PHP error message - to the user.

It depends if the web site is in production or is a released product. The last thing you want to do is show the user a stack trace for example. If you're expecting an error which could cause a fatal problem, then catch and handle it.

Related

PHP Exceptions redirected to custom error page

The functions I have written are throwing exceptions if they can't do their job. For the productive environment I thought to redirect the exception to a nice looking error page. Therefore I'm thinking of setting the exception handler set_exception_handler on the beginning of every script. How does the error page know which error occured? I thought of putting an error code into the URL like header("Location: error.php?code=1234"). While in the development phase I just would not set the exception handler, thus every exception would be printed onto the php default error screen Uncaugt Exception: ... with all usefull informations.
I have read Exceptions in PHP - Try/Catch or set_exception_handler? but don't know how to write a front controller script and also think this is maybe to much the effort.
I'm a PHP beginner who likes to handle errors in the right way, but I'm just not sure if I'm doing it right or wrong. Do you think it's ok doing it like above described or do you have other suggestions?
Thank you!
Don't redirect. In your exception handler function just output the error page at that point (or include a PHP file which includes the error page HTML). You also want to set an appropriate status code (using the PHP header function).
Edit: Why not to redirect:
You want to return an appropriate HTTP status code on your error pages (usually 404, 403, 400, 500 or 503 depending on the cause), so that search engine robots know not to index the error, crawlers can identify broken pages, browsers know not to cache the page and so on. If you redirect, you are returning a 301/302 HTTP status code and not one of the error ones.
You want users to be able to refresh the page with the error on, in case it was a temporary glitch. If you redirect them to another URL, however many times they refresh they will always see your error page (since that's the page they're on).
Well to tell you the truth I think it's too early for you to worry about this kind of things.
For now just keen on mastering OOP, because later on you WILL (and probably will have to) use a MVC framework, which does all the error/exception catching for you. Take a look at symfony: in development environment it shows you exception and stack trace, but in production env. it spits out a nice, customizable error page.
What i mean is: Don't reinvent the wheel, see how others solved similar problems. And preferably use their solutions (but remember to understand them as well).
Do you think it's ok doing it like
above described or do you have other
suggestions?
No, I don't think this is an OK solution. You don't want to apply a golden hammer to every problem that arises. Some exceptions should be handled differently than others. Furthermore, a particular exception may need to be handled differently in one part of the code than another. I would suggest set_exception_handler acts as a last resort, handling those exceptions that for some reason were not properly caught and go forward writing try/catches to handle things more granularly.

What is the correct way to use exceptions with PHP?

I have always the "return status code" method to manage errors. It seems that exceptions are nowdays the best formed way to manage errors.
But are they really the best way ? I have read stuff like exceptions are worst than GoTo
Do you know some good articles/posts/books about exceptions and error management?
If you program object orientated, maybe exceptions are better for you. If you write procedural, return values are the better way. It depends on your coding style etc.
Exceptions are about 10000x slower than returning a status/error code depending on the programming language. This is due to all the stack information being kept track of. That's the bad.
In general, you don't ever have to use exceptions. In fact, at one point, the only thing that existed was return codes.
The nice thing about exceptions is that they won't let a program continue unless they are dealt with correctly. Instead, the program crashes.
So, basically, if you are forgetful about handling status messages or are worried that others may not check return codes from your functions, exceptions stop the program and make you fix it. Although, I have seen a lot of inexperienced programmers catch the exception, not do anything about it, and then continue on. This is basically the same as ignoring the return code from a function.
One other nice thing about exceptions is that they "bubble up" automatically. Instead of having to pass back error codes through a long chain of functions, you could set up your try catch at the very top level and handle any error appropriately (assuming you didn't want anything else to happen in between). For example, if anything goes wrong, display an error page.

When to use Try Catch blocks

Ok, this might be a very noob question, but I find that PHP Documentation on that and several Internet Searches hasn't give me any idea about that.
When should I use try-catch blocks to improve my application?
I read someone saying that we should use try-catch blocks only to prevent fatal errors.
I read someone else saying that we should use it only on unexpected errors (wait what? unexpected? if they are unexpected errors how could I prevent them with try-catch? should I put all my application code inside a try block?).
Others simply say that try-catch blocks should be used everywhere because they can be also extended (extending the Exception class).
Finally someone says that PHP try-catch block are totally useless because they are very bad implemented. (On this I found a nice SO question about performance).
It seems to me that this topic is very strange and confused. Could someone lights me up?
It seems to me that this topic is very strange and confused. Could someone lights me up?
Definitely. I'm not a PHP user, but I might have a little insight after having worked with try/catch in ActionScript, Java, and JavaScript. Bear in mind though, that different languages and platforms encourage different uses for try/catch. That said...
The only times I'd recommend using try/catch is if you're using a native language function that
Can throw an error/exception
Does not give you any tools to detect whether you're about to do something stupid that would cause that error/exception. eg: In ActionScript, closing a loader that is not open will result in an error but the loader doesn't have an isOpen property to check so you're forced to wrap it in try/catch to silence an otherwise totally meaningless error.
The error/exception really is meaningless.
Let's take the examples you list and see how they square with that list.
I read someone saying that we should use try-catch blocks only to prevent fatal errors.
In the case of AS's loader.close() function, this is good advice. That's a fatal error, and all from an otherwise trivial misstep. On the other hand, virtually ALL errors in AS will bring your application to a halt. Would you then wrap them all in try/catch? Absolutely not! A "fatal error" is fatal for a reason. It means something terribly wrong has happened and for the application to continue on in a potentially "undefined" state is foolhardy. It's better to know an error happened and then fix it rather than just let it go.
I read someone else saying that we should use it only on unexpected errors
That's even worse. Those are presicely the errors you DON'T want to silence, because silencing them means that you're never going to find them. Maybe you're not swallowing them, though... maybe you're logging them. But why would you try/catch/log/continue as though nothing happened, allowing the program to run in a potentially dangerous and unexpected condition? Just let the error kick you in the teeth and then fix it. There's little more frustrating than trying to debug something that's wrong in a program that someone else wrote because they wrapped everything in a try/catch block and then neglected to log.
Others simply say that try-catch blocks should be used everywhere because they can be also extended (extending the Exception class).
There's potential merit to this if you're the one doing the throwing, and you're trying to alert yourself to an exceptional situation in your program... but why try/catch your own thrown error? Let it kick you in the teeth, then fix it so that you don't need to throw the error anymore.
Finally someone says that PHP try-catch block are totally useless because they are very bad implemented. (On this i find a nice SO question about performance).
Maybe so. I can't answer this one though.
So... this might be a bit of a religious question, and I'm certain people will disagree with me, but from my particular vantage point those are the lessons I've learned over the years about try/catch.
Different people will tell you different things. But this is what I think, specifically in the case of a web application.
Your whole page should be in a try/catch that displays an error message to the user. The error message shouldn't tell the user what happened in detail because thats a security concern. It should record information about the error into a log file.
The other case is where something could go wrong in the normal operation of affairs. PHP is not very exception happy so this may not happen very much. Basically, if you run into a function that throws an exception when it fails, you can catch the exception and do something else in that case.
In general, your question is like asking how you would use a hammer to improve the qualify of a house. Use exceptions to help you implement particular behaviors. Don't look for places to use exceptions.
I think it's simply a matter of preferences, but from my experiences, I'd encourage you to use them as much as possible.
In application we currently develop at work (using Zend Framework if it matters), we use one single try..catch block to catch all exceptions throughout the application which are shown to user as, for example, error 500s and exception is logged with more information to database. I, personally, love this approach in case of PHP application as exceptions are extendable and you can basically write whatever functionality you need.
I predominantly use Try/Catch around database calls...especially inputs, updates and deletes etc.
I sometimes use it around complex data processing with arrays and loops using dynamic data and arrays where there is a chance something might go wrong, ie: missing array elements or something (I normally check for stuff like that though).
I also use them around operations over which I don't have complete control such as importing data from an external or foreign data source where there could be problems with the data or accessing the source file.
I think what is meant by "Unexpected Errors" is where you can't prevent problems through good programming practices such as checking if a file exists before "including" it, Some problems you CAN anticipate so use good practices to prevent them. Don't just leave them to chance by wrapping them in a try/catch.
Use good programming practices instead as you should do everywhere. Don't use try/catch as a lazy shortcut for everything, everywhere. That's major overkill.
I agree with #scriptocalypse. In fact I only use try/catch blocks in PHP in 2 kind of situations.
If it's possible that some external (not inside my code) issues or DB errors may take place:
Getting data from another source (eg. curl)
Getting data from files
DB-Exceptions
If I work inside another system, like a CMS or similar and I want to override a certain behavior. For example I don't want an Exception being thrown but the exceptions message being returned to the view.
You cant put try catch blocks everywhere.
However during application testing, exceptions generated should alert you to places where you need try catches. This is one reason why you should run thorough testing of you application/code.
If you see a place where you think you need it, i would put one in.
EDIT: ok you CAN put them everywhere, but you need some sense as to where to put them in your code.
I normally put Try and Catch around areas in the code that have external forces acting on it that I have no control over. For example, Opening and reading external files.. you have no control that at some point in the reading of the file, the file becomes corrupted or something else happens that you can not control like the file server dc's or something

Overriding PEAR error handler

I'm currently working on an application that requires lots of external libraries. My job right now is set a unique error handler that will manage every error.
So far, I found 7 different types of PEAR errors:
PEAR_ERROR_RETURN:
PEAR_ERROR_EXCEPTION:
PEAR_ERROR_CALLBACK:
PEAR_ERROR_PRINT:
PEAR_ERROR_TRIGGER:
PEAR_ERROR_DIE:
I want to handle only the serious error (like the native E*_ERROR). The only problem is I have absolutely no idea about PEAR error criticity ! Those names are more related to the way of handling them than to their seriousness... Is there a real documentation about it ?
I guess a better solution would consist in using their pushErrorHandling, but I just don't understand how to use it... If someone here knows, I'd be grateful...
Thanks in advance !
From your question it sounds like you're wanting a single function to handle all warnings, errors, and exceptions.
For E_ERROR, I think you're out of luck. That indicates a fatal runtime error that PHP cannot recover from, so your script is doomed to fail.
With exceptions you can do a set_exception_handler("funcName"); to handle all uncaught exceptions in your program execution. However, this should be an absolute last resort for handling exceptions. A safety net, if you will, for anything that slips through the cracks of your try/catches. The reason for this (and for handling any error globally like this) is that you have no way to recover from the exception since set_exception_handler doesn't return a value and it has exited the program stack anyway.
Use try/catch generously in your application. It may seem tedious, or a waste of time, but the truth is that your program will fail at some point. It is inevitable, no matter how good a programmer you are. Proper use of exception handling will allow your application to gracefully close, or even recover properly from an exception.

Error Handling in Model (MVC)

I was wondering what the excepted standard is for handling errors in the Model.
Currently I have 'setError' and 'getError' methods that's in use by all my Models.
This means I'm only concerned with whether a call to a method in my Model is true or false. If it's false then I would use $this->model->getError() in my Controller.
Additionally I'm contemplating setting up a separate file that contains all my errors. One file per model, also wanted to have thoughts on this.
A simpler solution would be to use exceptions.
When an error occurs that would be something you display to a user, throw a special kind of an exception - perhaps named UserError. The exception should contain the text of the error message when you throw it. These kinds of errors are features which provide users with useful information (i.e. they attempted to delete something that did not exist - which can happen when they have multiple browsers open, etc.)
e.g.:
throw new UserError("That object no longer exists.");
When an error occurs that you want to hide from the user, throw a different kind of exception, perhaps named InternalError. You would want to log this and allow the program to continue, so the specific error is hidden from the user. If it prevents something from happening, you might want to throw up a generic error message. These would be bugs and you want to fix them as soon as possible.
e.g.:
throw new InternalError("Failed to connect to remote service");
All of the error messages can be stored (hard-coded) in the source where the exception is thrown. This is not necessarily a bad design practice - if you use a tool like gettext, you can easily translate all of these messages.
I've been using log4j and log4cxx and logging to a syslogd. Kiwi is a simple Win32 syslogger that will track your log messages and save them to a file. Log4j / Log4cxx have configuration files that you can use to setup all your log levels or log message destinations (you can log to multiple places).
It takes so little effort to setup and use, and it works like a charm.
I haven't tried out log4php myself.
Exceptions are good when you no longer want your program to continue executing. Catch exceptions at a high level where you can accept the fall-out of failed executions.
Review the NerdDinner tutorial on how to create validation routines before making a final decision:
http://nerddinnerbook.s3.amazonaws.com/Part3.htm
The Validation part is about 2/3 of the way down the page.

Categories