Trapping connection errors with mysqli

I have a connection include that is:

$link = new mysqli(‘localhost’, ‘root’, ‘pw’, ‘dbname’);
if (mysqli_connect_errno())
{
$error = 'Unable to connect to the database server.Error # ’ . mysqli_connect_errno();
header("Location: " . $_SESSION[‘uwserver’] . “/System_Error”);
exit();
}
When I force this to fail by using the wrong pw for example, it sends an error to the existing page:

Warning: mysqli::mysqli() [mysqli.mysqli]: (28000/1045): Access denied for user ‘root’@‘localhost’ (using password: YES) in C:\htdocs\includes02173\db.inc.php on line 2

I would like to trap this error before it sends this message and send a more user friendly message in it’s place. So first question is how do I prevent this message from being sent. Obviously I don’t want the db username and hostname being displayed on the page.

The second issue is that at the point when the script is calling for the connection, headers have already been sent. So this gives rise to a couple of questions.

  1. Is there any way to clear the headers and resend them in the form of an error page?

  2. If I were to create the connection earlier in the script, how long does it persist? i.e. is it like a session variable where I can access the same connection later in another script or do I need to open a new one each time I start executing a new script? My page is being built in sections, so things like the header and navigation sections go out and then some part of the page may require a db connection to be built, that is where I am running into the problem. It all works fine if it connects okay, it’s only when I force the error that I am seeing this but I want to make sure that it is all handled properly should this error occur. In reality, the site will be pretty useless without a db connection so it should be considered a fatal error, i.e. the site is down if they cannot connect to the database.

Sorry, no good links in my bookmarks, but what you need to do at least is:

error_reporting(-1); // E_ALL and other constants are available http://php.net/manual/en/function.error-reporting.php, but -1 guarantees you will see ALL and not SOME :|
ini_set('display_errors', 1); // or 0 for production, this affects output on the page only
ini_set('log_errors', 1); // log all errors no matter what
ini_set('error_log', '/some/file'); // will default to using your apache log if not set

You can do this in a variety of ways (php.ini, .htaccess, code as above), and also check out set_error_handler and [URL=“http://php.net/manual/en/function.set-exception-handler.php”]set_exception_handler.

There was a problem with statements in earlier versions of PDO where you had to explicitly close them unless you fetched all the results, but I believe this is fixed. If you’re having problems, I doubt it will be memory, but rather I/O in which case you can look at buffered vs unbuffered queries.

Output buffer is used as a cureall for bad code mostly, but it does have good use in templating systems, either way, worth understanding.

Thanks so much. There goes my weekend! :slight_smile:

I really appreciate the time and the input. Cheers.

This isn’t about mysqli, it’s about error handling. In production you want to set display_errors = off, in dev you want it on. For trapping, you can set a custom error and exception handler (e.g. to forward to 404 or 500 pages).

Re the second issue, no, nothing can be unsent, but you can do a couple of things:

  1. do all of your logic (db connection, user is valid, query model etc) before you start to output
  2. start an output buffer (which doesn’t stop headers being sent, but makes sure you don’t send any content till you are ready - ie you can still send headers).
  3. it persists as long as your script runs. PHP scripts come into life on a page request, and then die killing everything they created. There are a number of ways to make sure you only have one db object, the simplest (from your description) is to only create one, all includes will have access to this.

Regarding the error handling, any good articles or resources you can point to on that? If not, no worries, I’ll find it. :slight_smile:

On the second issue, thanks, that helps a bunch. I am in the process now of following the script and all the includes all the way through and using only one connection from the initial calling script. I have been pretty sloppy in managing this so this is a good opportunity to clean all that up anyhow.

So also as I am going through this, if I am using prepared statements, I should issue a $result->close for each query as I am done with it to clear memory and also because as I understand it, I can’t have two prepared statements open under one db connection, is that true?

I will look more into the output buffer and see where I can use that, thanks for the heads up.