I think I understand how exceptions work in php5, but have not tried to code up anything using them. I am more familiar with exceptions in python and java. But it seems since the internal/core php functions don't throw exceptions, I will just end up with code bloat.
Is it really worth using them if all you are doing is converting return values to exceptions by hand, every place you may have a bad return value. If i'm using bulit-in functions, do I need to check return values and then make up my own custom exception handlers that only exist in my code, along with anything I wrote with my own custom exceptions? That seems like a _lot_ of extra lines of code added to convert a php4 script to php5.
Is the solution to write a custom error handler that turns everything non-fatal into an exception? Even so, won't my sub-classed exceptions be useless to other programmers and projects? Should someone distribute a file with common error/exception mapping? Shouldn't php have this already?
One other thing. If I use the error handler to turn all errors into exceptions then am I required to use " catch( Exception $e ) " around just about everything since an uncaught exception is an fatal-error in itself? Again this seems like code bloat?
Is the tactic to actually use exceptions sparingly only in custom functions/objects? If they are going to be so rare and special case, then why bother with them at all?But it seems since the internal/core php functions don't throw exceptions, I will just end up with code bloat.
It's not true that the internal / core stuff doesn't throw exceptions, just *most of* the older stuff doesn't.
PDO, for example, has an optional throw-exceptions mode which you can turn on when creating the connection object - I always do so.
Is it really worth using them if all you are doing is converting return values to exceptions by hand, every place you may have a bad return value.
No, but you should not do that. Instead wrap the existing errors, warnings and notices in an exception. That means you won't require any per-case code at all to cause exceptions to be thrown appropriately throughout your entire app.
If i'm using bulit-in functions, do I need to check return values and then make up my own custom exception handlers that only exist in my code, along with anything I wrote with my own custom exceptions?
No, absolutely not. Register an error handler which throws an exception (if the error isn't masked).
Is the solution to write a custom error handler that turns everything non-fatal into an exception?
Yes, that's ideal.
Even so, won't my sub-classed exceptions be useless to other programmers and projects? Should someone distribute a file with common error/exception mapping? Shouldn't php have this already?
Maybe. I think it would be useful. I wouldn't bother creating a new class for every type of error, just use the same one for them all.
One other thing. If I use the error handler to turn all errors into exceptions then am I required to use " catch( Exception $e ) " around just about everything since an uncaught exception is an fatal-error in itself? Again this seems like code bloat?
No, absolutely absolutely not. Code running normally should not cause any errors / warnings / notices during normal operation, so it's perfectly safe to let these exceptions go uncaught.
Also you can register a handler for uncaught exceptions- which I do to invoke the behaviour that previously existed in my error handler in PHP4.
Is the tactic to actually use exceptions sparingly only in custom functions/objects? If they are going to be so rare and special case, then why bother with them at all?
I use them everywhere, but I rarely subclass Exception- usually I just throw Exception itself.
MarkI think I should reiterate - normal code should cause ABSOLUTELY NO warnings, errors or even notices under normal conditions- therefore it is highly advisable to have all of these throw an exception which then goes uncaught, halting the page.
If your code causes *even* E_NOTICEs under normal operation, it is broken and MUST be fixed.
For rare cases where you absolutely cannot avoid a warning / notice, mask that warning specifically by changing error_reporting (remember to change it back afterwards).
MarkDon't make the mistake of equating Exceptions to errors or warnings. Two completely different concepts. I'd suggest reading a few articles on the use of Exceptions. They can be tricky. One key point is to avoid using Exceptions for flow control. Only use Exceptions for, well, exceptional cases.I don't like using the terms "flow control" or "exceptional case" because exceptions don't have to be "exceptional cases" -- that term is to strong for me -- and they certainly do control the flow... they reverse it back up the call stack.
Exceptions are for when a method encounters some condition that it does not know how to deal with. So it throws an Exception back up the call stack in the hope that somewhere up the chain will be someone who knows how to deal with it.
The term I see used most to describe when to use Exceptions is "abnormal" conditions. I like this because it is less strong of a word and more clear. It means "not usual" and there can only be two cases usual or not usual. Semantically "exceptional" tends to be a subset of abnormal and refers to something being far or widely outside of what is usual. I know it is just semantics, but using exceptional bugs the crap out of me because it is less clear and leaves 3 cases: usual, not usual but not exceptional, and exceptional.
I also don't like leaving Exceptions uncaught. While it may be true PHP with then throw a fatal error, a bit friendlier message can certainly be given. One thing that really bugs me about PHP is that when it kicks out a fatal error, it still sends an HTTP 200 OK header. I cannot tell you the number of sites I've seen indexed on Google with fatal error messages because something abnormal occured and Google was updating their index of them at around the same time. I always have a catch block at the top level for those rare cases where nothing else knows what to do with the Exception. In the block I then send an HTTP 500 Internal Server Error with the Exception message, as I find that to be more appropriate, more helpful, and more HTTP friendly. At least you will not be caught by a spider with your pants around your ankles
Finally I don't agree with ahundiak with not equating Exceptions to warnings. I would only not equate exceptions to PHP errors that are related to running the VM. However, in my opinion standard errors that PHP gives related to functionality not pertaining to the VM certainly can be wrapped in Exceptions. I would not be surprised, and would even hope, that at some point in the future, errors that PHP generated were limited in scope to errors dealing with the VM and all other errors were thrown as Exceptions. For example, your application tries to read or write to a file. If the file cannot be opened, that is in my opinion an Exception that can be recovered from in some way (even if the file absolutely must be written for some reason, it could be written as a temp file until the problem is corrected). However, PHP will throw a warning or something, so to correctly make it an Exception case without also getting the silly PHP errors, you have to use error suppression which tends to make experienced PHP develops cringe, though I am getting used to it when the error is being suppressed to use an Exception instead.usual, not usual but not exceptional, and exceptional.
What, like "order 5 cauliflowers", "order 24,000 cauliflowers" and "order -54smoo cauliflowers"?
I also don't like leaving Exceptions uncaught.Well, you're not supposed to do that anyway. In any language that provides exception handling it's expected that if you throw an exception you'll catch it at some point. Failing to do so is considered a bug in its own right.
And leaving error messages (even PHP-triggered ones) around for the world to see is just dumb anyway.
Using exception handling is a noticeable performance hit. ...I was going to write a bit more but decided I'd just chuck in a few comments from the MSDN .NET library:
Know when to set up a try/catch block. For example, you can programmatically check for a condition that is likely to occur without using exception handling. In other situations, using exception handling to catch an error condition is appropriate.
Return null for extremely common error cases. For example, File.Open returns null if the file is not found, but throws an exception if the file is locked.
Design classes so that an exception is never thrown in normal use. For example, a FileStream class exposes another way of determining whether the end of the file has been reached. This avoids the exception that is thrown if you read past the end of the file.
Is it really worth using them if all you are doing is converting return values to exceptions by hand, every place you may have a bad return value. If i'm using bulit-in functions, do I need to check return values and then make up my own custom exception handlers that only exist in my code, along with anything I wrote with my own custom exceptions? That seems like a _lot_ of extra lines of code added to convert a php4 script to php5.
Is the solution to write a custom error handler that turns everything non-fatal into an exception? Even so, won't my sub-classed exceptions be useless to other programmers and projects? Should someone distribute a file with common error/exception mapping? Shouldn't php have this already?
One other thing. If I use the error handler to turn all errors into exceptions then am I required to use " catch( Exception $e ) " around just about everything since an uncaught exception is an fatal-error in itself? Again this seems like code bloat?
Is the tactic to actually use exceptions sparingly only in custom functions/objects? If they are going to be so rare and special case, then why bother with them at all?But it seems since the internal/core php functions don't throw exceptions, I will just end up with code bloat.
It's not true that the internal / core stuff doesn't throw exceptions, just *most of* the older stuff doesn't.
PDO, for example, has an optional throw-exceptions mode which you can turn on when creating the connection object - I always do so.
Is it really worth using them if all you are doing is converting return values to exceptions by hand, every place you may have a bad return value.
No, but you should not do that. Instead wrap the existing errors, warnings and notices in an exception. That means you won't require any per-case code at all to cause exceptions to be thrown appropriately throughout your entire app.
If i'm using bulit-in functions, do I need to check return values and then make up my own custom exception handlers that only exist in my code, along with anything I wrote with my own custom exceptions?
No, absolutely not. Register an error handler which throws an exception (if the error isn't masked).
Is the solution to write a custom error handler that turns everything non-fatal into an exception?
Yes, that's ideal.
Even so, won't my sub-classed exceptions be useless to other programmers and projects? Should someone distribute a file with common error/exception mapping? Shouldn't php have this already?
Maybe. I think it would be useful. I wouldn't bother creating a new class for every type of error, just use the same one for them all.
One other thing. If I use the error handler to turn all errors into exceptions then am I required to use " catch( Exception $e ) " around just about everything since an uncaught exception is an fatal-error in itself? Again this seems like code bloat?
No, absolutely absolutely not. Code running normally should not cause any errors / warnings / notices during normal operation, so it's perfectly safe to let these exceptions go uncaught.
Also you can register a handler for uncaught exceptions- which I do to invoke the behaviour that previously existed in my error handler in PHP4.
Is the tactic to actually use exceptions sparingly only in custom functions/objects? If they are going to be so rare and special case, then why bother with them at all?
I use them everywhere, but I rarely subclass Exception- usually I just throw Exception itself.
MarkI think I should reiterate - normal code should cause ABSOLUTELY NO warnings, errors or even notices under normal conditions- therefore it is highly advisable to have all of these throw an exception which then goes uncaught, halting the page.
If your code causes *even* E_NOTICEs under normal operation, it is broken and MUST be fixed.
For rare cases where you absolutely cannot avoid a warning / notice, mask that warning specifically by changing error_reporting (remember to change it back afterwards).
MarkDon't make the mistake of equating Exceptions to errors or warnings. Two completely different concepts. I'd suggest reading a few articles on the use of Exceptions. They can be tricky. One key point is to avoid using Exceptions for flow control. Only use Exceptions for, well, exceptional cases.I don't like using the terms "flow control" or "exceptional case" because exceptions don't have to be "exceptional cases" -- that term is to strong for me -- and they certainly do control the flow... they reverse it back up the call stack.
Exceptions are for when a method encounters some condition that it does not know how to deal with. So it throws an Exception back up the call stack in the hope that somewhere up the chain will be someone who knows how to deal with it.
The term I see used most to describe when to use Exceptions is "abnormal" conditions. I like this because it is less strong of a word and more clear. It means "not usual" and there can only be two cases usual or not usual. Semantically "exceptional" tends to be a subset of abnormal and refers to something being far or widely outside of what is usual. I know it is just semantics, but using exceptional bugs the crap out of me because it is less clear and leaves 3 cases: usual, not usual but not exceptional, and exceptional.
I also don't like leaving Exceptions uncaught. While it may be true PHP with then throw a fatal error, a bit friendlier message can certainly be given. One thing that really bugs me about PHP is that when it kicks out a fatal error, it still sends an HTTP 200 OK header. I cannot tell you the number of sites I've seen indexed on Google with fatal error messages because something abnormal occured and Google was updating their index of them at around the same time. I always have a catch block at the top level for those rare cases where nothing else knows what to do with the Exception. In the block I then send an HTTP 500 Internal Server Error with the Exception message, as I find that to be more appropriate, more helpful, and more HTTP friendly. At least you will not be caught by a spider with your pants around your ankles
Finally I don't agree with ahundiak with not equating Exceptions to warnings. I would only not equate exceptions to PHP errors that are related to running the VM. However, in my opinion standard errors that PHP gives related to functionality not pertaining to the VM certainly can be wrapped in Exceptions. I would not be surprised, and would even hope, that at some point in the future, errors that PHP generated were limited in scope to errors dealing with the VM and all other errors were thrown as Exceptions. For example, your application tries to read or write to a file. If the file cannot be opened, that is in my opinion an Exception that can be recovered from in some way (even if the file absolutely must be written for some reason, it could be written as a temp file until the problem is corrected). However, PHP will throw a warning or something, so to correctly make it an Exception case without also getting the silly PHP errors, you have to use error suppression which tends to make experienced PHP develops cringe, though I am getting used to it when the error is being suppressed to use an Exception instead.usual, not usual but not exceptional, and exceptional.
What, like "order 5 cauliflowers", "order 24,000 cauliflowers" and "order -54smoo cauliflowers"?
I also don't like leaving Exceptions uncaught.Well, you're not supposed to do that anyway. In any language that provides exception handling it's expected that if you throw an exception you'll catch it at some point. Failing to do so is considered a bug in its own right.
And leaving error messages (even PHP-triggered ones) around for the world to see is just dumb anyway.
Using exception handling is a noticeable performance hit. ...I was going to write a bit more but decided I'd just chuck in a few comments from the MSDN .NET library:
Know when to set up a try/catch block. For example, you can programmatically check for a condition that is likely to occur without using exception handling. In other situations, using exception handling to catch an error condition is appropriate.
Return null for extremely common error cases. For example, File.Open returns null if the file is not found, but throws an exception if the file is locked.
Design classes so that an exception is never thrown in normal use. For example, a FileStream class exposes another way of determining whether the end of the file has been reached. This avoids the exception that is thrown if you read past the end of the file.