PHP error handling working in MySQL & MySQLi but not PDO

Issue

I’ve just finished refactoring a bunch of MySQL and MySQLi forms to PDO.

Everything seems to be working.

Now on to error handling.

In the MySQL / MySQLi code I had been using if statements to catch errors. Like this:

if (!$database_connection) {    
    // error handling here
}

Plain and simple.

But I can’t get a similar set-up to work with PDO.

Here’s the scenario:

I have a connection to a database that looks something like this:

$data_source_name = "mysql:host=$db_host;dbname=$db_name";
$database_connection = new PDO($data_source_name, $db_username, $db_password);

The execution looks something like this:

$stmt= $database_connection->prepare($sql);
$stmt->execute([$name, $email]);

I’m trying to set up a condition like the one described above:

if ( database connection fails ) {
   // error handling
}

But this code doesn’t work.

if ( !$database_connection ) {
     // error handling
} else {
    $stmt= $database_connection->prepare($sql);
    $stmt->execute([$name, $email]);
}

This if construct worked in MySQL (now deprecated) and works in MySQLi, but not PDO.

Per a suggestion from another Stack user, I tried setting a variable to the execution code, like this:

$result = $stmt->execute([$order, $foods]);

… and running the if statement on that. But that just inserts duplicates in the database.

Note that I was originally trying to make this work using trycatch, as recommended in many Stack posts. But after more research I’ve concluded that this function is inappropriate for PDO Exceptions.

Any guidance and suggestions appreciated. Thanks.

Solution

It’s a very common fallacy, that one needs a dedicated error handling code for PDO or Mysqli (or whatever else module for that matter). Least it should be even more specific, such as "Mysqli connection" handler, as it seems with your old mysqli code.

If you think of it, you don’t really care whether it was exactly a database error that prevented the code form being executed correctly. There can be any other problem as well.

Admittedly, one hardly can expect any other problem from such a simple code but still, the code may grow, become more modular, perform more tasks – and therefore error out in any other part as well. Like, writing database credentials in the every file is a bit of waste. So it’s natural to put them in a file and then just include it in the every other script that requires a database interaction. So this file may get corrupted which will has the same effect as a database error. And will need to be fixed as well.

Or, if you’re handling only the connection error, the problem can happen during the query execution as well (especially in your case, as the way the query is executed it will error out even if a customer will simply enter fish'h'chips for example).

What you really care for is whether the data has been stored correctly (and probably whether emails were sent as well) or not, no matter what could be the possible failure. This is being the exact reason, why I wrote in the article this warning against wrapping some specific part of code in a try-catch in order to report this particular error. As error reporting handler must be common for the entire code.

Admittedly, the simplest exception handling method is simply wrapping the entire code in a try catch block where the most generic exception type, namely Throwable, must be checked for. Not very reliable but simplest.

The key here is to wrap the entire code, not just some random part of it. But one shouldn’t forget to set the exception mode for PDO, in order let the query execution errors to be caught in this block as well.

<?php
try {
    require 'pdo.php'
    ...
    $sql = "INSERT INTO other_choices (order,foods) VALUES (?,?)";
    ...
    $stmt= $db_connection->prepare($sql);
    $stmt->execute([$order, $foods]);

    // send emails, etc
} catch (Throwable $e) {
    // do your handling here
}

Note that I substituted actual variables in the query with question marks, which is being correct way of using prepared statements, that otherwise become useless and render all your transition from mysqli fruitless (especially given that mysqli supports prepared statements as well).

Unfortunately, PHP has two kinds of errors – exceptions and errors proper. And try-catch can catch only the former. In order to handle all kinds of errors, an error handler can be used. You can see a very basic example of one in my article on PHP error reporting.

The last note: sending an email every time an error occurs on the site is not the wisest move. Although in your case it could be justified, given PHP is only involved when a user submits a form, but on a regular site, where PHP is used to handle every page, it can lead to thousands emails. Or even in your case, spammers may target your forms and send thousands requests as well (which itself may cause some overflow error and therefore thousands emails in the inbox). Instead of sending emails manually, consider using a dedicated error monitoring software, such as Sentry. It will send only new errors, as well as aggregated error info.

Answered By – Your Common Sense

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published