The (im)proper use of try..catch.

  1. Delusion
  2. TL;DR
  3. Disclosure
  4. Clarification
  5. Example
  6. Comments (13)

Delusion

Most examples of try..catch operator you can find on the Net are something like this:

try {
    $stmt = $dbh->prepare($sql);
    $stmt->execute($data);
} catch (PDOException $e) {
    die($e->getMessage());
}

Shamefully, PHP manual is especially bad at it, having such examples all over PDO and other extensions examples.

TL;DR

Never use try-catch for the basic error reporting. Just leave exceptions alone:

$stmt = $dbh->prepare($sql);
$stmt->execute();

Disclosure

Such a code is a result of a mere confusion. Look, what you actually have from it:

An error message being thrown right on the screen,

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'foo' at line 1

Looks exactly what you were looking for? Not quite.

NONE of these things you actually want.

Clarification

As a matter of fact, you are writing this code only to be visually notified of the error, if it happened during development. The funny part is that for such a cause you need no extra code at all. I am not kidding. PHP is quite good with reporting errors, and need no extra assistance. If you leave your PDO code alone, adding no useless try..catch stuff, an exception will be translated into a fatal error, and PHP will be happy to report this fatal error usual way, just like any other error message.

That's the point.

Unlike your unconditional approach, PHP will follow site-wide configuration options, set for the whole server. If you want error messages to be shown right on the screen, just set the proper option for this: display_errors. That's all. In case of error, it will be revealed to you. Moreover, it will contain whole error message, including exact file name and line number where error occurred. And even more - a stack trace, which will help you to track down the code that actually caused the error:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'foo' at line 1' in /srv/hosting/html/another_file.php:5
Stack trace:
#0 /srv/hosting/html/another_file.php(5): PDO->query('foo')
#1 /srv/hosting/html/pdo.php(23): demo()
#2 {main}

Here you can see the full error message you were depriving yourself from.

Let's closely examine it

And all that treasure without a single extra line of code! Just with default PHP settings! Isn't it wonderful?

All right, but what about production environment? That's very interesting question. In fact, most PHP users consider themselves the only users of their site. And that custom of catching and echoing every error is a sure proof for that - it's intended for the programmer only but inconvenient for the users. While in reality sometimes sites go live, and require totally different error handling in this case.

To handle an error on a live site we actually need:

And again - PHP already can do it all for us! If we turn display_errors=off, while log_errors= on, PHP will do all the things automatically - log error, show error page and HTTP code. As of the custom error page, it is best to be handled by the web-server (ErrorDocument for Apache and error_page for Nginx).

— But I am doing it only for debugging purpose!!!

Well, you are doing it wrong. A programmer have to be notified of errors any time, no matter which mode is on.

Example

— But what if I want something more complex than just showing/logging?

In such a case you can setup a Custom Exception Handler like this

set_exception_handler('myExceptionHandler');
function myExceptionHandler($e)
{
    header('HTTP/1.1 500 Internal Server Error', TRUE, 500);
    error_log($e);
    readfile ('500.html');
    exit;
}

or, for a more general handling not only exceptions but all errors,

set_error_handler("myErrorHandler");
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    error_log("$errstr in $errfile:$errline");
    header('HTTP/1.1 500 Internal Server Error', TRUE, 500);
    readfile("500.html");
    exit;
}

written just once it will relieve you from writing handling code again and again.

— All right, but is here a case when try..catch can be useful?

Sure! Just use try..catch only if you going to handle the error itself. Say, there is a code to process uploaded images. An error in such processing is not a fatal one and can be handled - so, that's the right place for the try..catch!

try {
    processUploadedImage($file);
} catch (Exception $e) {
    $formHandlerErrors[] = "There is an error processing uploaded image";
}

In short, if your error is recoverable and you have a certain scenario to recover - then use try..catch.


Related articles: