How does throw work? - php

I would like to know how throw works in PHP.
For example, does it act like a die() or exit()? How can I know what is done internally?
I am asking this because I saw Kohana using their $this->redirect() method with a throw to terminate the script execution instead of the traditional exit.

throw is not like exit or die at all. Throwing an exception does not automatically terminate the application, a thrown exception can be caught by the application. Only when an exception is not caught will the application be terminated.
try {
throw new Exception;
} catch (Exception $e) {
echo 'caught it';
}
echo 'not dead yet';
Exceptions are a mechanism to signal errors to higher up callers in a more flexible and rigorous manner than simple return false statements would allow. They are not comparable to a simple exit or die.
I don't know what Kohana does exactly, but throwing an exception instead of using a simple exit or die is an abuse of exceptions. Exceptions should be thrown in exceptional error circumstances only.

As already explained, you use throw to throw exceptions that can be caught "further up" in your application.
When you work with objects and object oriented programming you start coding every single object you make as a standalone object that you can give to someone else. The public methods of these are an API, and the phpdoc above each public method details what exceptions the class might throw under certain circumstances.
So, someone has created a standalone object that does something for you, like writing to a disk. You want to use this object, so you look at the docs and see it throws a PermissionsException when the object can't write to the disk because of a permissions issue.
In your code that uses this person's object, you now know that you should catch that exception, log it, and continue however you want your application to work given that circumstance (show a nice error to the user if it's via an AJAX call, for example).
So, knowing this, when you code your own objects, make descriptive exceptions for different circumstances that someone who you give your object to can use and respond to in their own applications.
Both die and exit you don't really want to use in production applications. They're useful for debugging when you do a var_dump() and then want to halt application execution straight afterwards or if you want to completely stop the script from running for some reason.
As for why your specific found piece of code does it this way, you should ask the developer if it isn't documented with good reasoning.

Using "throw" without try/catch will terminate the script with a "catchable fatal error". As far as I know there's no benefit in using "throw" this way. If you want to terminate a script you should use exit(), so you don't need to suppress the error message.

Related

set_exception_handler for specific exceptions

I'm using a new API and I want to handle exceptions specific to it, and return the data from the exceptions to JS function that made a request. The thing is - I have a fatal_handler registered with register_shutdown_function in the program, and I want to avoid it for these exceptions, because It won't let me return the necessary data to the JS function, and I don't want to mess with this specific handler because it's more general.
I managed to override it with set_exception_handler, but I assume it will catch other unhandled exceptions as well.
Is there any way to define the instance of the exception (e.g AException) that will be handled in set_exception_handler(), same as in a catch block?
My only idea was to check the type of the exception object I'm getting to the handler function (with instanceof, and rethrow it if it's not the type I'm looking for.

PHP, how to make a function catch, catch PDOExceptions

Can you have a method throw any exceptions that occurs within it's method body? I want to automatically 'throw' any PDO related exceptions without always having to use 'try/catch' blocks within a function/method.
Example:
function testExcption($a..) throws PDOException{
// PDO related code here.
}
So can I 'throw' and exception at the function/method declaration level and without any try/catch blocks?
EDIT
I'm trying to avoid always having to write 'try/catch' because I only care for the PDO related exceptions that can occur within those functions/methods. I have lots of methods/functions and I'm tired of using 'try/catch' all the time for PDO error handling, and again I only care for the PDO exceptions in those functions/methods. Does that make sense?
EDIT
Is there a way to get PDO errors w/o try/catch blocks?
Maybe you are mixing things. Throwing exceptions is done without any try/catch statment. Throwing Exceptions is as easy as:
function nonsensefunc(){
throw new Exception('<Description of Error>');
}
On the other side, when calling you function, you have to use try/catch, you are catching them.
So what happens, when you do not catch the errors? The Exception is thrown a level higher and finally is printed out. Mostly it triggers an abort in PHP and stops the rest of the script.
So what is your expected behaviour? The only way of doing other thing as the default behaviour (printing the error and stopping) is to catch it.

How do I document "trigger_error()" for a class method?

If I have the following class method:
class ClassA
{
public function MethodA()
{
trigger_error('An error has occurred.', E_USER_ERROR);
}
}
... then what is the accepted way of documenting that it might "throw" (issue) an error using trigger_error() explicitly? The closest I found was to use either #throws, or #exception. Is it possible this behavior should not be documented at all, or instead included in the method description itself?
The reason I ask this question about trigger_error is because I use a custom error logging class which is called by a custom error handler, hence it is convenient to issue runtime errors and output/save them in an organized fashion. Should I just use #see trigger_error or #see ErrorLog (my custom class) instead?
EDIT:
For those wondering about the script flow if an error is triggered: the script will not terminate execution on E_USER_ERROR.
The script will not terminate execution on E_USER_ERROR.
This may be your bigger issue. PHP's error mechanism is rather... primitive. It basically only knows two modes: notify the developer of potential issues by triggering a notice, warning or stern warning (a.k.a. error), or to stop the script by triggering a fatal error. Triggering a (fatal) error yet continuing with the script execution is not really its purpose.
The function should simply be documented informally with "triggers error if X, Y or Z". This typically means "will kill script if X, Y or Z". If you're overriding that behaviour, that's up to you.
Formally documented errors make sense if those errors can be handled in a standardised manner, which is very much what exceptions are. They have formal documentation standards (#throws) and can be handled in flexible ways (try..catch). You really should use exceptions for the purpose you're trying to use errors here.

suggestions for unit testing exceptions

Consider a method which might throw an exception with some descriptive text:
if ($someCondition) {
throw new \Whatever\Exception('dilithium exhausted');
}
And elsewhere in the method is another block that might throw the same exception, but with different text:
if ($anotherCondition) {
throw new \Whatever\Exception('differentialator exploded');
}
While writing unit tests for this class, you create failure cases so that you can verify that these two exceptions get thrown properly. In these failure cases, do you prefer to:
A) Use #exceptionExpected in the test method's docblock to trap the generic \Whatever\Exception class and subsequently ignore the getMessage() text, assuming you got the right one? (Seems like a bad idea.)
or:
B) Use try/catch and then assert that the caught exception's getMessage() text equals the exact descriptive string you're expecting? (More resilient but it means changing your tests whenever you change your error wording.)
or:
C) Create a separate exception for each error case (e.g., \Whatever\DilithiumException and \Whatever\DifferentialatorException) and then use #exceptionExpected for each one.
I'm currently using B but tending toward C. I'm curious what others are doing in this same scenario. Do you have any guidelines that help you determine, "At what point does an error deserve its own exception class versus a more generic shared one?"
All of the above.
A is great, and I use as much as possible because it is simplest. There is another case when A does not work:
/**
* #exceptionExpected FooException
*/
test() {
// code that could throw FooException
...
// purpose of the test that throws of FooException
}
In this case, the test could pass when it should have failed because it didn't even get to what I was testing. A good way to deal with this is to use $this->setExpectedException()
B is great when you might actually use information from the exception. Rather than using the text of the exception message I would prefer to use the code. I have a form validation exception that packages up all the problems encountered in the data into one exception. By extending the exception class it becomes easy to transmit a good deal of information from the internal error state to the external handling code.
C accomplishes the same thing as B, but allows for simplifying the code by relying on more classes. The difference between these two is subtle and I tend to rely on design aesthetic to make the decision.
TL; DR: Use exception codes rather than messages, and design to the use case rather than the unit tests.
PHPUnit also provides #expectedExceptionCode and #expectedExceptionMessage when you need this level of detail. Warning: The latter requires the former.
BTW, I also tend toward A. If I need to express more meaning in the exception, I prefer to create a new exception class. I find the message to be too volatile to be worth testing in most applications.

Has trigger_error() in PHP been deprecated for something better in PHP5?

I used to use this when I wanted to trigger errors in PHP, coming from a PHP4 background. Note I had my own set_error_handler() for handling these errors.
if ($error) {
trigger_error('Sorry, error has occured');
}
I can't remember where, but sometime ago someone told me I should be 'using exceptions'. As I'm re factoring a lot of my old code, I figured now is the time to get some good advice on my error handling implementation.
Now that I'm using PHP5 (and a bit smarter than I was when I wrote the older code), is my trigger_error() just an old way of doing things, and if so, what is the best way to handle errors in PHP5?
Yes, you may want to start looking into the PHP 5 exception model. Remember though that just because something is new doesn't mean that you must adopt it. Only adopt those features that you need and make sense in your domain.
That being said, I feel that exceptions are a good concept to grasp and even if you decide not to adopt them you will be all the better for the experience.
I would like to suggest that you read PHP: Exceptions - Manual:
PHP 5 has an exception model similar
to that of other programming
languages. An exception can be thrown,
and caught ("catched") within PHP.
Code may be surrounded in a try block,
to facilitate the catching of
potential exceptions. Each try must
have at least one corresponding catch
block. Multiple catch blocks can be
used to catch different classes of
exeptions. Normal execution (when no
exception is thrown within the try
block, or when a catch matching the
thrown exception's class is not
present) will continue after that last
catch block defined in sequence.
Exceptions can be thrown (or
re-thrown) within a catch block.
I would also encourage you to read What Is an Exception? (Note this is a Java tutorial but the concepts are universal)
When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.
Edit: In order to implement a global exception handler (basically in order to establish a default exception handler that will handle previously unhandled exceptions) you will want to us the set_exception_handler function.
Using exceptions is the object-oriented way to trigger and handle your own application errors.
The PHP manual topic on exceptions is probably a good place to start.
Here is a small example:
function doSomething() {
if ($error) {
throw new Exception('Some descriptive error message.');
}
}
try {
doSomething();
}
catch (Exception $e) {
die('<p class="error">' . $e->getMessage() . '</p>');
}

Categories