133

In regards to Error handling in PHP -- As far I know there are 3 styles:

  1. die()or exit() style:

    $con = mysql_connect("localhost","root","password");
    
    if (!$con) {
     die('Could not connect: ' . mysql_error());
    }
    
  2. throw Exception style:

     if (!function_exists('curl_init')) {
    
          throw new Exception('need the CURL PHP extension. 
                               Recomplie PHP with curl');
        }
    
  3. trigger_error() style:

    if(!is_array($config) && isset($config)) {
            trigger_error('Error: config is not an array or is not set', E_USER_ERROR);
        }
    

Now, in the PHP manual all three methods are used.

  • What I want to know is which style should I prefer & why?

  • Are these 3 drop in replacements of each other & therefore can be used interchangeably?

Slightly OT: Is it just me or everyone thinks PHP error handling options are just too many to the extent it confuses php developers?

Chris Toxz
  • 32
  • 6
CuriousMind
  • 33,537
  • 28
  • 98
  • 137

2 Answers2

94

The first one should never be used in production code, since it's transporting information irrelevant to end-users (a user can't do anything about "Cannot connect to database").

You throw Exceptions if you know that at a certain critical code point, your application can fail and you want your code to recover across multiple call-levels.

trigger_error() lets you fine-grain error reporting (by using different levels of error messages) and you can hide those errors from end-users (using set_error_handler()) but still have them be displayed to you during testing.

Also trigger_error() can produce non-fatal messages important during development that can be suppressed in production code using a custom error handler. You can produce fatal errors, too (E_USER_ERROR) but those aren't recoverable. If you trigger one of those, program execution stops at that point. This is why, for fatal errors, Exceptions should be used. This way, you'll have more control over your program's flow:

// Example (pseudo-code for db queries):

$db->query('START TRANSACTION');

try {
    while ($row = gather_data()) {
       $db->query('INSERT INTO `table` (`foo`,`bar`) VALUES(?,?)', ...);
    }
    $db->query('COMMIT');
} catch(Exception $e) {
    $db->query('ROLLBACK');
}

Here, if gather_data() just plain croaked (using E_USER_ERROR or die()) there's a chance, previous INSERT statements would have made it into your database, even if not desired and you'd have no control over what's to happen next.

Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • 2
    so out of `trigger_error()` & throwing exceptions: which one should I use & when? – CuriousMind Aug 15 '11 at 09:01
  • @Gaurish See the added example on that. – Linus Kleen Aug 15 '11 at 09:12
  • 2
    After reading your example, I think now I understand the purpose behind throw exception better. Thanks :) – CuriousMind Aug 15 '11 at 10:50
  • @LinusKleen, you say that a rogue `gather_data()` could cause half-done inserts. However, commit was not even run, so the inserts would not be carried out right? – Pacerier Jul 16 '13 at 18:29
  • 1
    @Pacerier That depends on the server's configuration, actually. A system *might* be configured to [autocommit](http://stackoverflow.com/questions/2280465/how-do-i-turn-off-autocommit-for-a-mysql-client) per default, hence the explicit `ROLLBACK`. This pseudo-code example covers both cases: servers which aren't configured to autocommit (the `COMMIT` statement is required) and those that do. – Linus Kleen Jul 16 '13 at 18:46
  • 1
    @LinusKleen, isn't autocommit turned off once we run the line `query('START TRANSACTION');`? – Pacerier Jul 16 '13 at 19:46
  • @Pacerier A valid question, though it exceeds the scope of the OP's question and my answer. The real question to ask would be *"Why is there a `ROLLBACK` instruction?"* Considering things *should* never be committed, unless you explicitly fire a `COMMIT` statement. – Linus Kleen Jul 16 '13 at 20:25
  • @Linus, It's to rollback the transaction for non-fatal errors, so that he can continue program execution, e.g. starting a new transaction. Both `rollback` and `commit` separates the first transaction from the second transaction. – Pacerier Jul 16 '13 at 20:30
  • @Pacerier You have answered your comment question yourself, in a way. Nowhere in the docs does it state that the rollback instruction is for "non-fatal errors". If some code is designed to make use of more than one transaction, you'll *need* to cancel the first in order to initiate a second (hence the `ROLLBACK`). Let's please agree that this discussion is not part of the OP's question. – Linus Kleen Jul 16 '13 at 20:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33651/discussion-between-linus-kleen-and-pacerier) – Linus Kleen Jul 17 '13 at 16:58
  • @LinusKleen Let's agree that if you are not sure about something then you shouldn't have it as part of your accepted answer (you said it yourself, it exceeds the scope of the question), since you will confuse future readers. By the way, you are wrong. Those "rogue" insert will never make it to the database, Yes, the database may be implicitly set to "auto commit", but you are 100% "explicitly" overriding it by creating/handling the transaction yourself, so there are no doubts anymore, unless you are using a broken/bugged DBMS, in which case you got bigger problems. – Gam Jun 11 '17 at 05:12
11

I usually use the first way for simple debugging in development code. It is not recommended for production. The best way is to throw an exception, which you can catch in other parts of the program and do some error handling on.

The three styles are not drop-in replacements for each other. The first one is not an error at all, but just a way to stop the script and output some debugging info for you to manually parse. The second one is not an error per se, but will be converted into an error if you don't catch it. The last one is triggering a real error in the PHP engine which will be handled according to the configuration of your PHP environment (in some cases shown to the user, in other cases just logged to a file or not saved at all).

Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
  • 2
    What happens when exception is thrown but not caught? it will cause a fatal error, I guess. And with `trigger_error()` same thing happens. so what's the difference? – CuriousMind Aug 15 '11 at 09:04
  • 4
    The difference is that you can catch the exception and handle it in any way you want. – Emil Vikström Aug 15 '11 at 09:38
  • @EmilVikström But errors can also by catched by a custom error handler. Also since PHP7 errors and exception both based on the throwable interface. Since PHP8 there is also an class named Error. When I look into the class definition of this class and compared it with the Exception class the only difference was the class name. So I would assume that the Error class is a descendant of the Exception class. But I'm not sure. – Alexander Behling Aug 31 '21 at 09:43
  • 1
    Per the PHP manual: "Error is the base class for all internal PHP errors." "Exception is the base class for all user exceptions." Neither extends the other, though they both implement the Throwable interface. – Bob Ray Jul 29 '22 at 02:53