16

I'm doing this (yes, I'm using wrong connection data, it's to force a connection error )

try {
    $connection = new mysqli('localhost', 'my_user', 'my_password', 'my_db') ;
} catch (Exception $e ) {
    echo "Service unavailable";
    exit (3);
}

But PHP is doing this php_warning:

mysqli::mysqli(): (28000/1045): Access denied for user 'my_user'@'localhost' (using password: YES)

In the example I'm using wrong connection data to force a connection error, but in the real world the database could be down, or the network could be down... etc..

Question: Is there a way, without suppressing warnings, to intercept a problem with the database connection ?

Dharman
  • 30,962
  • 25
  • 85
  • 135
realtebo
  • 23,922
  • 37
  • 112
  • 189

4 Answers4

41

You need to tell mysqli to throw exceptions:

mysqli_report(MYSQLI_REPORT_STRICT);

try {
     $connection = new mysqli('localhost', 'my_user', 'my_password', 'my_db') ;
} catch (Exception $e ) {
     echo "Service unavailable";
     echo "message: " . $e->message;   // not in live code obviously...
     exit;
}

Now you will catch the exception and you can take it from there.

jeroen
  • 91,079
  • 21
  • 114
  • 132
  • 2
    It's a pretty bad idea to show the end user the error message. It's a potential security risk, it's better to log the error to a file and siaplay a generic errror message. – Rob Sedgwick Sep 28 '15 at 08:42
  • This does not handle the case where the database does not exist. – HoldOffHunger Jun 09 '16 at 13:06
  • @HoldOffHunger Yes it does, why wouldn't it? Note that you'll likely get a "access denied" error in that case. – jeroen Jun 10 '16 at 14:51
  • 1
    @YourCommonSense To illustrate on SO what is happening and what information is available about the exception? – jeroen Jun 10 '16 at 14:59
  • 1
    This is brillient. I have mine set up for the server but I like to default to localhost when I am on a local machine so I was using connect_errno to check if there was a connection error and then going to localhost. This is a much better solution as it doesn't show an error – Thomas Williams Mar 09 '17 at 19:29
9

For PHP 5.2.9+

if ($mysqli->connect_error) {
    die('Connect Error, '. $mysqli->connect_errno . ': ' . $mysqli->connect_error);
}

You'll want to set the Report Mode to a strict level as well, just as jeroen suggests, but the code above is still useful for specifically detecting a connection error. The combination of those two approaches is what's recommended in the PHP manual.

TonyArra
  • 10,607
  • 1
  • 30
  • 46
  • 1
    The @ operator has a lot of problems and should be avoided. Jeroen has a much better solution. – GordonM Mar 02 '16 at 11:23
  • This is the right approach. Unfortunately, this will not correctly report a non-existent database, to which I have provided a solution here. – HoldOffHunger Jun 09 '16 at 13:06
2

Check $connection->connect_error value.

See the example here: http://www.php.net/manual/en/mysqli.construct.php

ulentini
  • 2,413
  • 1
  • 14
  • 26
-3

mysqli_report(MYSQLI_REPORT_STRICT);, as described elsewhere, gives me an error and stops the script immediately. But this below seems to provide the desired output for me...

error_reporting(E_ERROR);

$connection = new mysqli('localhost', 'my_user', 'my_password', 'my_db') ;

error_reporting(E_ERROR | E_WARNING | E_PARSE);

if($connection->connect_errno)
{
  // Database does not exist, you lack permissions, or some other possible error.
    if(preg_match($connection->connect_error, "Access denied for user"))
    {
        print("Access denied, or database does not exist.");
    }
    else
    {
        print("Error: " . $connection->connect_error);
    }
}

Attempting to catch this error with try..catch() will fail.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
  • 1
    There is nothing desirable in telling a site user that they don't have whatever permissions. Your idea on error handling is essentially wrong. – Your Common Sense May 30 '16 at 04:31
  • @Your Common Sense: There is everything desirable in telling a site user about database permissions, if that site user is also a member of the db-admin team. Your criticism applies equally to the OP's question. – HoldOffHunger May 30 '16 at 15:46
  • 1
    There is even more nothing desirable in showing to a member of the db-admin team a *fake* error message, which is deliberately artificial and may have nothing in common with the real problem occurred. – Your Common Sense May 30 '16 at 16:00
  • Did you read the OP's post? "mysqli::mysqli(): (28000/1045): Access denied for user 'my_user'@'localhost' (using password: YES) " That is the error message for a non-existent database or a database without permission. The print statement is the equivalent of a comment. I'm demonstrating how the code can work. – HoldOffHunger May 30 '16 at 23:56
  • 1
    Did you read the OP's post? "*I'm using wrong connection data to force a connection error, but in the real world the database could be down, or the network could be down... etc..*". Access denied is not the only error that can ever occur. There are thousands other errors. Your code will repeat the same message for all of them. – Your Common Sense May 31 '16 at 04:00
  • How would you detect that a database doesn't exist with MySQLi, then? – HoldOffHunger Jun 02 '16 at 22:09
  • I don't understand your question. You want to check the database existence, report a non-existent database error or handle this error? All three tasks have different solutions. – Your Common Sense Jun 03 '16 at 03:45
  • I only mentioned the first one, the other two problems you raise are only tangential. How would you detect, using PHP's MySQLi only, that a database doesn't exist? My method does the job (no, it's not an entire error-handling module, it's not supposed to be). Do you have a method? – HoldOffHunger Jun 04 '16 at 00:05
  • using `SHOW DATABASES LIKE database_name` query? – Your Common Sense Jun 04 '16 at 06:55
  • 2
    Looks finally I managed to understand your confusion. It is based on the "*gives me an error and stops the script immediately.*" statement. To handle an exception, in case you have a certain scenario for a certain error, you have to use `try..catch` operator, checking for this particular error, handling it, or - in case the error is something different, re-throwing the exception to let the script die immediately in peace. Example you may find here: https://phpdelusions.net/pdo#errors – Your Common Sense Jun 04 '16 at 06:59
  • Thank you, that's exactly my point. SHOW DATABASES and new mysqli() give conflicting, different error messages. try..catch indicates an incorrect error message, which is why I avoided your suggestion, as indicated by OP, and others posting. – HoldOffHunger Jun 07 '16 at 13:15
  • Looks like you are under some delusion caused by whatever confusion. Show tables doesn'give you an error message, as well as try..catch. – Your Common Sense Jun 07 '16 at 17:11
  • Run this. Catch block never executes. connect_error . "|"); } catch(Exception $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; } ?> – HoldOffHunger Jun 09 '16 at 13:05
  • It's not like your code fails like you have a simple syntax error. It's more like your code fails like you don't even know which conditionals pass or fail and which blocks of code subsequently get executed. – HoldOffHunger Jun 09 '16 at 13:16